Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System')
-rw-r--r--src/System.Private.CoreLib/shared/System/AccessViolationException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ApplicationException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ArgumentException.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/ArgumentNullException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/ArithmeticException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ArraySegment.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/BadImageFormatException.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/BitConverter.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Boolean.cs108
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs25
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs75
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs95
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs161
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs216
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/Byte.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/Char.cs88
-rw-r--r--src/System.Private.CoreLib/shared/System/CharEnumerator.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Comparer.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs61
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs834
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs332
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs1115
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs551
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs172
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs1650
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ICollection.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IComparer.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IList.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs36
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs36
-rw-r--r--src/System.Private.CoreLib/shared/System/Convert.Base64.cs217
-rw-r--r--src/System.Private.CoreLib/shared/System/Convert.cs709
-rw-r--r--src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs46
-rw-r--r--src/System.Private.CoreLib/shared/System/DataMisalignedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/DateTime.cs241
-rw-r--r--src/System.Private.CoreLib/shared/System/DateTimeOffset.cs109
-rw-r--r--src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs2648
-rw-r--r--src/System.Private.CoreLib/shared/System/Decimal.cs1121
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs302
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs81
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs588
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs39
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs46
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs106
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs52
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs76
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/DivideByZeroException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/DllNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Double.cs79
-rw-r--r--src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/EventHandler.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/FieldAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/FormatException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/FormattableString.cs23
-rw-r--r--src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs76
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs99
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs63
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs426
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs1074
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs647
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs275
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs356
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs348
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs100
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs690
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs44
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs129
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs162
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs21
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs24
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs48
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs193
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs2293
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs96
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs111
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs120
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs315
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs351
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs326
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Guid.Unix.cs38
-rw-r--r--src/System.Private.CoreLib/shared/System/Guid.Windows.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Guid.cs32
-rw-r--r--src/System.Private.CoreLib/shared/System/HResults.cs3
-rw-r--r--src/System.Private.CoreLib/shared/System/IAsyncResult.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IComparable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IConvertible.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/ICustomFormatter.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IFormatProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IFormattable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs717
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs36
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs53
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs140
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/IOException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs34
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs101
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.cs187
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs66
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PathInternal.cs129
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Stream.cs1322
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/StreamReader.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs187
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/TextReader.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/TextWriter.cs176
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs110
-rw-r--r--src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Int16.cs54
-rw-r--r--src/System.Private.CoreLib/shared/System/Int32.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Int64.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/IntPtr.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidCastException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidOperationException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidProgramException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Lazy.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Marvin.cs143
-rw-r--r--src/System.Private.CoreLib/shared/System/Math.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/MemberAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Memory.cs186
-rw-r--r--src/System.Private.CoreLib/shared/System/MemoryDebugView.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs267
-rw-r--r--src/System.Private.CoreLib/shared/System/MemoryExtensions.cs479
-rw-r--r--src/System.Private.CoreLib/shared/System/MethodAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/MissingFieldException.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/MissingMemberException.cs78
-rw-r--r--src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NotImplementedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NotSupportedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NullReferenceException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Nullable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Number.Formatting.cs517
-rw-r--r--src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Number.Parsing.cs1489
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt17
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude61
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Register.cs132
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Register.tt2
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Vector.cs4501
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Vector.tt647
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/OperationCanceledException.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs45
-rw-r--r--src/System.Private.CoreLib/shared/System/OverflowException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Random.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/RankException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs127
-rw-r--r--src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs15
-rw-r--r--src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs3
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs32
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs75
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs2539
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs191
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs19
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Module.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs142
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs1184
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs262
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs100
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs61
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs609
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs86
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs98
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs245
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs54
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs53
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs344
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs344
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs44
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs46
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs43
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs1230
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs1412
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs1915
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs2641
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs96
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs96
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs189
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs190
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs190
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs606
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs631
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs1763
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs2002
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs91
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs90
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs636
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs636
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs304
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs304
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs116
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs116
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs25
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs515
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/SByte.cs52
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SecureString.cs19
-rw-r--r--src/System.Private.CoreLib/shared/System/Single.cs83
-rw-r--r--src/System.Private.CoreLib/shared/System/Span.Fast.cs15
-rw-r--r--src/System.Private.CoreLib/shared/System/Span.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanDebugView.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs509
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs420
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs109
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.cs220
-rw-r--r--src/System.Private.CoreLib/shared/System/StackOverflowException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/String.Comparison.cs905
-rw-r--r--src/System.Private.CoreLib/shared/System/String.Manipulation.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/String.Searching.cs274
-rw-r--r--src/System.Private.CoreLib/shared/System/String.cs794
-rw-r--r--src/System.Private.CoreLib/shared/System/StringComparer.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs142
-rw-r--r--src/System.Private.CoreLib/shared/System/SystemException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs124
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Decoder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Encoder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Encoding.cs50
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs37
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs263
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs62
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs84
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs92
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs324
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs284
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs120
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs340
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs93
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs759
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs100
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Mutex.cs62
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs88
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs67
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs945
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs650
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs754
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs510
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs45
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs781
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeSpan.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZone.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs27
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs262
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs89
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeoutException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Tuple.cs144
-rw-r--r--src/System.Private.CoreLib/shared/System/Type.Helpers.cs43
-rw-r--r--src/System.Private.CoreLib/shared/System/Type.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/TypeInitializationException.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/UInt16.cs50
-rw-r--r--src/System.Private.CoreLib/shared/System/UInt32.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/UInt64.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/UIntPtr.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/ValueTuple.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Version.cs30
428 files changed, 58448 insertions, 11657 deletions
diff --git a/src/System.Private.CoreLib/shared/System/AccessViolationException.cs b/src/System.Private.CoreLib/shared/System/AccessViolationException.cs
index 280d9b8a9..a66f2a892 100644
--- a/src/System.Private.CoreLib/shared/System/AccessViolationException.cs
+++ b/src/System.Private.CoreLib/shared/System/AccessViolationException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.E_POINTER;
}
- public AccessViolationException(String message)
+ public AccessViolationException(string message)
: base(message)
{
HResult = HResults.E_POINTER;
}
- public AccessViolationException(String message, Exception innerException)
+ public AccessViolationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.E_POINTER;
diff --git a/src/System.Private.CoreLib/shared/System/ApplicationException.cs b/src/System.Private.CoreLib/shared/System/ApplicationException.cs
index f36e2c127..cac29196b 100644
--- a/src/System.Private.CoreLib/shared/System/ApplicationException.cs
+++ b/src/System.Private.CoreLib/shared/System/ApplicationException.cs
@@ -39,13 +39,13 @@ namespace System
// message, its HRESULT set to COR_E_APPLICATION,
// and its ExceptionInfo reference set to null.
//
- public ApplicationException(String message)
+ public ApplicationException(string message)
: base(message)
{
HResult = HResults.COR_E_APPLICATION;
}
- public ApplicationException(String message, Exception innerException)
+ public ApplicationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_APPLICATION;
diff --git a/src/System.Private.CoreLib/shared/System/ArgumentException.cs b/src/System.Private.CoreLib/shared/System/ArgumentException.cs
index 8a8fe3e5e..5a918063e 100644
--- a/src/System.Private.CoreLib/shared/System/ArgumentException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArgumentException.cs
@@ -23,7 +23,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ArgumentException : SystemException
{
- private String _paramName;
+ private string _paramName;
// Creates a new ArgumentException with its message
// string set to the empty string.
@@ -36,26 +36,26 @@ namespace System
// Creates a new ArgumentException with its message
// string set to message.
//
- public ArgumentException(String message)
+ public ArgumentException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public ArgumentException(String message, Exception innerException)
+ public ArgumentException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public ArgumentException(String message, String paramName, Exception innerException)
+ public ArgumentException(string message, string paramName, Exception innerException)
: base(message, innerException)
{
_paramName = paramName;
HResult = HResults.COR_E_ARGUMENT;
}
- public ArgumentException(String message, String paramName)
+ public ArgumentException(string message, string paramName)
: base(message)
{
_paramName = paramName;
@@ -74,14 +74,14 @@ namespace System
info.AddValue("ParamName", _paramName, typeof(string));
}
- public override String Message
+ public override string Message
{
get
{
- String s = base.Message;
- if (!String.IsNullOrEmpty(_paramName))
+ string s = base.Message;
+ if (!string.IsNullOrEmpty(_paramName))
{
- String resourceString = SR.Format(SR.Arg_ParamName_Name, _paramName);
+ string resourceString = SR.Format(SR.Arg_ParamName_Name, _paramName);
return s + Environment.NewLine + resourceString;
}
else
@@ -89,7 +89,7 @@ namespace System
}
}
- public virtual String ParamName
+ public virtual string ParamName
{
get { return _paramName; }
}
diff --git a/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs b/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs
index 80e43cc26..edc38f2a4 100644
--- a/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs
@@ -30,19 +30,19 @@ namespace System
HResult = HResults.E_POINTER;
}
- public ArgumentNullException(String paramName)
+ public ArgumentNullException(string paramName)
: base(SR.ArgumentNull_Generic, paramName)
{
HResult = HResults.E_POINTER;
}
- public ArgumentNullException(String message, Exception innerException)
+ public ArgumentNullException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.E_POINTER;
}
- public ArgumentNullException(String paramName, String message)
+ public ArgumentNullException(string paramName, string message)
: base(message, paramName)
{
HResult = HResults.E_POINTER;
diff --git a/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs b/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs
index 604caa8ee..8d91561ce 100644
--- a/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs
@@ -22,7 +22,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ArgumentOutOfRangeException : ArgumentException
{
- private Object _actualValue;
+ private object _actualValue;
// Creates a new ArgumentOutOfRangeException with its message
// string set to a default message explaining an argument was out of range.
@@ -32,19 +32,19 @@ namespace System
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
- public ArgumentOutOfRangeException(String paramName)
+ public ArgumentOutOfRangeException(string paramName)
: base(SR.Arg_ArgumentOutOfRangeException, paramName)
{
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
- public ArgumentOutOfRangeException(String paramName, String message)
+ public ArgumentOutOfRangeException(string paramName, string message)
: base(message, paramName)
{
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
- public ArgumentOutOfRangeException(String message, Exception innerException)
+ public ArgumentOutOfRangeException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
@@ -53,7 +53,7 @@ namespace System
// We will not use this in the classlibs, but we'll provide it for
// anyone that's really interested so they don't have to stick a bunch
// of printf's in their code.
- public ArgumentOutOfRangeException(String paramName, Object actualValue, String message)
+ public ArgumentOutOfRangeException(string paramName, object actualValue, string message)
: base(message, paramName)
{
_actualValue = actualValue;
@@ -72,14 +72,14 @@ namespace System
info.AddValue("ActualValue", _actualValue, typeof(object));
}
- public override String Message
+ public override string Message
{
get
{
- String s = base.Message;
+ string s = base.Message;
if (_actualValue != null)
{
- String valueMessage = SR.Format(SR.ArgumentOutOfRange_ActualValue, _actualValue.ToString());
+ string valueMessage = SR.Format(SR.ArgumentOutOfRange_ActualValue, _actualValue.ToString());
if (s == null)
return valueMessage;
return s + Environment.NewLine + valueMessage;
@@ -92,7 +92,7 @@ namespace System
// Note - we don't set this anywhere in the class libraries in
// version 1, but it might come in handy for other developers who
// want to avoid sticking printf's in their code.
- public virtual Object ActualValue
+ public virtual object ActualValue
{
get { return _actualValue; }
}
diff --git a/src/System.Private.CoreLib/shared/System/ArithmeticException.cs b/src/System.Private.CoreLib/shared/System/ArithmeticException.cs
index 606f1debf..46492cab5 100644
--- a/src/System.Private.CoreLib/shared/System/ArithmeticException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArithmeticException.cs
@@ -34,13 +34,13 @@ namespace System
// message, its HRESULT set to COR_E_ARITHMETIC,
// and its ExceptionInfo reference set to null.
//
- public ArithmeticException(String message)
+ public ArithmeticException(string message)
: base(message)
{
HResult = HResults.COR_E_ARITHMETIC;
}
- public ArithmeticException(String message, Exception innerException)
+ public ArithmeticException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARITHMETIC;
diff --git a/src/System.Private.CoreLib/shared/System/ArraySegment.cs b/src/System.Private.CoreLib/shared/System/ArraySegment.cs
index 3a13595e8..b2bd41780 100644
--- a/src/System.Private.CoreLib/shared/System/ArraySegment.cs
+++ b/src/System.Private.CoreLib/shared/System/ArraySegment.cs
@@ -131,7 +131,7 @@ namespace System
System.Array.Copy(_array, _offset, destination._array, destination._offset, _count);
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj is ArraySegment<T>)
return Equals((ArraySegment<T>)obj);
@@ -289,7 +289,7 @@ namespace System
bool ICollection<T>.Remove(T item)
{
ThrowHelper.ThrowNotSupportedException();
- return default(bool);
+ return default;
}
#endregion
diff --git a/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs b/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs
index 49820f58f..2f60fd4ea 100644
--- a/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs
@@ -34,13 +34,13 @@ namespace System
// message, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
// and its ExceptionInfo reference set to null.
//
- public ArrayTypeMismatchException(String message)
+ public ArrayTypeMismatchException(string message)
: base(message)
{
HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
}
- public ArrayTypeMismatchException(String message, Exception innerException)
+ public ArrayTypeMismatchException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
diff --git a/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs b/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
index 1743075a6..c8cb65c64 100644
--- a/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
+++ b/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
@@ -21,8 +21,8 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial class BadImageFormatException : SystemException
{
- private String _fileName; // The name of the corrupt PE file.
- private String _fusionLog = null; // fusion log (when applicable)
+ private string _fileName; // The name of the corrupt PE file.
+ private string _fusionLog = null; // fusion log (when applicable)
public BadImageFormatException()
: base(SR.Arg_BadImageFormatException)
@@ -30,25 +30,25 @@ namespace System
HResult = HResults.COR_E_BADIMAGEFORMAT;
}
- public BadImageFormatException(String message)
+ public BadImageFormatException(string message)
: base(message)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
}
- public BadImageFormatException(String message, Exception inner)
+ public BadImageFormatException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
}
- public BadImageFormatException(String message, String fileName) : base(message)
+ public BadImageFormatException(string message, string fileName) : base(message)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
_fileName = fileName;
}
- public BadImageFormatException(String message, String fileName, Exception inner)
+ public BadImageFormatException(string message, string fileName, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
@@ -69,7 +69,7 @@ namespace System
info.AddValue("BadImageFormat_FusionLog", _fusionLog, typeof(string));
}
- public override String Message
+ public override string Message
{
get
{
@@ -91,14 +91,14 @@ namespace System
}
}
- public String FileName
+ public string FileName
{
get { return _fileName; }
}
- public override String ToString()
+ public override string ToString()
{
- String s = GetType().ToString() + ": " + Message;
+ string s = GetType().ToString() + ": " + Message;
if (_fileName != null && _fileName.Length != 0)
s += Environment.NewLine + SR.Format(SR.IO_FileName_Name, _fileName);
@@ -121,7 +121,7 @@ namespace System
return s;
}
- public String FusionLog
+ public string FusionLog
{
get { return _fusionLog; }
}
diff --git a/src/System.Private.CoreLib/shared/System/BitConverter.cs b/src/System.Private.CoreLib/shared/System/BitConverter.cs
index e3cf20eb6..8a8101ddc 100644
--- a/src/System.Private.CoreLib/shared/System/BitConverter.cs
+++ b/src/System.Private.CoreLib/shared/System/BitConverter.cs
@@ -376,7 +376,7 @@ namespace System
if (length > (int.MaxValue / 3))
{
- // (Int32.MaxValue / 3) == 715,827,882 Bytes == 699 MB
+ // (int.MaxValue / 3) == 715,827,882 Bytes == 699 MB
throw new ArgumentOutOfRangeException(nameof(length), SR.Format(SR.ArgumentOutOfRange_LengthTooLarge, (int.MaxValue / 3)));
}
diff --git a/src/System.Private.CoreLib/shared/System/Boolean.cs b/src/System.Private.CoreLib/shared/System/Boolean.cs
index fd56082f9..4daf6f3f9 100644
--- a/src/System.Private.CoreLib/shared/System/Boolean.cs
+++ b/src/System.Private.CoreLib/shared/System/Boolean.cs
@@ -12,7 +12,6 @@
**
===========================================================*/
-using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
@@ -20,12 +19,12 @@ namespace System
{
[Serializable]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean>
+ public readonly struct Boolean : IComparable, IConvertible, IComparable<bool>, IEquatable<bool>
{
//
// Member Variables
//
- private bool m_value; // Do not rename (binary serialization)
+ private readonly bool m_value; // Do not rename (binary serialization)
// The true value.
//
@@ -42,11 +41,11 @@ namespace System
// The internal string representation of true.
//
- internal const String TrueLiteral = "True";
+ internal const string TrueLiteral = "True";
// The internal string representation of false.
//
- internal const String FalseLiteral = "False";
+ internal const string FalseLiteral = "False";
//
@@ -55,11 +54,11 @@ namespace System
// The public string representation of true.
//
- public static readonly String TrueString = TrueLiteral;
+ public static readonly string TrueString = TrueLiteral;
// The public string representation of false.
//
- public static readonly String FalseString = FalseLiteral;
+ public static readonly string FalseString = FalseLiteral;
//
// Overriden Instance Methods
@@ -82,7 +81,7 @@ namespace System
**Exceptions: None.
==============================================================================*/
// Converts the boolean value of this instance to a String.
- public override String ToString()
+ public override string ToString()
{
if (false == m_value)
{
@@ -91,41 +90,57 @@ namespace System
return TrueLiteral;
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return ToString();
}
public bool TryFormat(Span<char> destination, out int charsWritten)
{
- string s = m_value ? TrueLiteral : FalseLiteral;
-
- if (s.AsSpan().TryCopyTo(destination))
+ if (m_value)
{
- charsWritten = s.Length;
- return true;
+ if ((uint)destination.Length > 3) // uint cast, per https://github.com/dotnet/coreclr/issues/18688
+ {
+ destination[0] = 'T';
+ destination[1] = 'r';
+ destination[2] = 'u';
+ destination[3] = 'e';
+ charsWritten = 4;
+ return true;
+ }
}
else
{
- charsWritten = 0;
- return false;
+ if ((uint)destination.Length > 4)
+ {
+ destination[0] = 'F';
+ destination[1] = 'a';
+ destination[2] = 'l';
+ destination[3] = 's';
+ destination[4] = 'e';
+ charsWritten = 5;
+ return true;
+ }
}
+
+ charsWritten = 0;
+ return false;
}
// Determines whether two Boolean objects are equal.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
//If it's not a boolean, we're definitely not equal
- if (!(obj is Boolean))
+ if (!(obj is bool))
{
return false;
}
- return (m_value == ((Boolean)obj).m_value);
+ return (m_value == ((bool)obj).m_value);
}
[NonVersionable]
- public bool Equals(Boolean obj)
+ public bool Equals(bool obj)
{
return m_value == obj;
}
@@ -137,18 +152,18 @@ namespace System
//
// Returns a value less than zero if this object
//
- public int CompareTo(Object obj)
+ public int CompareTo(object obj)
{
if (obj == null)
{
return 1;
}
- if (!(obj is Boolean))
+ if (!(obj is bool))
{
throw new ArgumentException(SR.Arg_MustBeBoolean);
}
- if (m_value == ((Boolean)obj).m_value)
+ if (m_value == ((bool)obj).m_value)
{
return 0;
}
@@ -159,7 +174,7 @@ namespace System
return 1;
}
- public int CompareTo(Boolean value)
+ public int CompareTo(bool value)
{
if (m_value == value)
{
@@ -176,20 +191,41 @@ namespace System
// Static Methods
//
+ // Custom string compares for early application use by config switches, etc
+ //
+ internal static bool IsTrueStringIgnoreCase(ReadOnlySpan<char> value)
+ {
+ return (value.Length == 4 &&
+ (value[0] == 't' || value[0] == 'T') &&
+ (value[1] == 'r' || value[1] == 'R') &&
+ (value[2] == 'u' || value[2] == 'U') &&
+ (value[3] == 'e' || value[3] == 'E'));
+ }
+
+ internal static bool IsFalseStringIgnoreCase(ReadOnlySpan<char> value)
+ {
+ return (value.Length == 5 &&
+ (value[0] == 'f' || value[0] == 'F') &&
+ (value[1] == 'a' || value[1] == 'A') &&
+ (value[2] == 'l' || value[2] == 'L') &&
+ (value[3] == 's' || value[3] == 'S') &&
+ (value[4] == 'e' || value[4] == 'E'));
+ }
+
// Determines whether a String represents true or false.
//
- public static Boolean Parse(String value)
+ public static bool Parse(string value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
return Parse(value.AsSpan());
}
public static bool Parse(ReadOnlySpan<char> value) =>
- TryParse(value, out bool result) ? result : throw new FormatException(SR.Format_BadBoolean);
+ TryParse(value, out bool result) ? result : throw new FormatException(SR.Format(SR.Format_BadBoolean, new string(value)));
// Determines whether a String represents true or false.
//
- public static Boolean TryParse(String value, out Boolean result)
+ public static bool TryParse(string value, out bool result)
{
if (value == null)
{
@@ -202,15 +238,13 @@ namespace System
public static bool TryParse(ReadOnlySpan<char> value, out bool result)
{
- ReadOnlySpan<char> trueSpan = TrueLiteral.AsSpan();
- if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsTrueStringIgnoreCase(value))
{
result = true;
return true;
}
- ReadOnlySpan<char> falseSpan = FalseLiteral.AsSpan();
- if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsFalseStringIgnoreCase(value))
{
result = false;
return true;
@@ -219,13 +253,13 @@ namespace System
// Special case: Trim whitespace as well as null characters.
value = TrimWhiteSpaceAndNull(value);
- if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsTrueStringIgnoreCase(value))
{
result = true;
return true;
}
- if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsFalseStringIgnoreCase(value))
{
result = false;
return true;
@@ -242,7 +276,7 @@ namespace System
int start = 0;
while (start < value.Length)
{
- if (!Char.IsWhiteSpace(value[start]) && value[start] != nullChar)
+ if (!char.IsWhiteSpace(value[start]) && value[start] != nullChar)
{
break;
}
@@ -252,7 +286,7 @@ namespace System
int end = value.Length - 1;
while (end >= start)
{
- if (!Char.IsWhiteSpace(value[end]) && value[end] != nullChar)
+ if (!char.IsWhiteSpace(value[end]) && value[end] != nullChar)
{
break;
}
@@ -332,7 +366,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -342,7 +376,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Boolean", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs
index 77a07f7fa..22ad7821f 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs
@@ -33,9 +33,7 @@ namespace System.Buffers
/// optimized for very fast access speeds, at the expense of more memory consumption.
/// The shared pool instance is created lazily on first access.
/// </remarks>
- public static ArrayPool<T> Shared { get; } =
- typeof(T) == typeof(byte) || typeof(T) == typeof(char) ? new TlsOverPerCoreLockedStacksArrayPool<T>() :
- Create();
+ public static ArrayPool<T> Shared { get; } = new TlsOverPerCoreLockedStacksArrayPool<T>();
/// <summary>
/// Creates a new <see cref="ArrayPool{T}"/> instance using default configuration options.
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs
index b2d0dbd32..d0563c497 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs
@@ -86,5 +86,19 @@ namespace System.Buffers
/// </summary>
[Event(3, Level = EventLevel.Verbose)]
internal void BufferReturned(int bufferId, int bufferSize, int poolId) => WriteEvent(3, bufferId, bufferSize, poolId);
+
+ /// <summary>
+ /// Event raised when we attempt to free a buffer due to inactivity or memory pressure (by no longer
+ /// referencing it). It is possible (although not commmon) this buffer could be rented as we attempt
+ /// to free it. A rent event before or after this event for the same ID, is a rare, but expected case.
+ /// </summary>
+ [Event(4, Level = EventLevel.Informational)]
+ internal void BufferTrimmed(int bufferId, int bufferSize, int poolId) => WriteEvent(4, bufferId, bufferSize, poolId);
+
+ /// <summary>
+ /// Event raised when we check to trim buffers.
+ /// </summary>
+ [Event(5, Level = EventLevel.Informational)]
+ internal void BufferTrimPoll(int milliseconds, int pressure) => WriteEvent(5, milliseconds, pressure);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs b/src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs
new file mode 100644
index 000000000..44f16c582
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs
@@ -0,0 +1,17 @@
+// 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.
+
+namespace System.Buffers
+{
+ /// <summary>
+ /// Owner of Memory<typeparamref name="T"/> that is responsible for disposing the underlying memory appropriately.
+ /// </summary>
+ public interface IMemoryOwner<T> : IDisposable
+ {
+ /// <summary>
+ /// Returns a Memory<typeparamref name="T"/>.
+ /// </summary>
+ Memory<T> Memory { get; }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs b/src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs
new file mode 100644
index 000000000..623e716a0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs
@@ -0,0 +1,25 @@
+// 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.
+
+namespace System.Buffers
+{
+ /// <summary>
+ /// Provides a mechanism for pinning and unpinning objects to prevent the GC from moving them.
+ /// </summary>
+ public interface IPinnable
+ {
+ /// <summary>
+ /// Call this method to indicate that the IPinnable object can not be moved by the garbage collector.
+ /// The address of the pinned object can be taken.
+ /// <param name="elementIndex">The offset to the element within the memory at which the returned <see cref="MemoryHandle"/> points to.</param>
+ /// </summary>
+ MemoryHandle Pin(int elementIndex);
+
+ /// <summary>
+ /// Call this method to indicate that the IPinnable object no longer needs to be pinned.
+ /// The garbage collector is free to move the object now.
+ /// </summary>
+ void Unpin();
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs b/src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs
deleted file mode 100644
index 6ac508859..000000000
--- a/src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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.Runtime;
-using System.Runtime.CompilerServices;
-
-namespace System.Buffers
-{
- /// <summary>
- /// Provides a mechanism for manual lifetime management.
- /// </summary>
- public interface IRetainable
- {
- /// <summary>
- /// Call this method to indicate that the IRetainable object is in use.
- /// Do not dispose until Release is called.
- /// </summary>
- void Retain();
- /// <summary>
- /// Call this method to indicate that the IRetainable object is no longer in use.
- /// The object can now be disposed.
- /// </summary>
- bool Release();
- }
-} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs b/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs
index 754403862..b218534c5 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs
@@ -2,7 +2,6 @@
// 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.Runtime;
using System.Runtime.InteropServices;
namespace System.Buffers
@@ -12,53 +11,48 @@ namespace System.Buffers
/// </summary>
public unsafe struct MemoryHandle : IDisposable
{
- private IRetainable _retainable;
private void* _pointer;
private GCHandle _handle;
+ private IPinnable _pinnable;
/// <summary>
/// Creates a new memory handle for the memory.
/// </summary>
- /// <param name="retainable">reference to manually managed object</param>
- /// <param name="pointer">pointer to memory, or null if a pointer was not provided when the handle was created</param>
+ /// <param name="pointer">pointer to memory</param>
+ /// <param name="pinnable">reference to manually managed object, or default if there is no memory manager</param>
/// <param name="handle">handle used to pin array buffers</param>
[CLSCompliant(false)]
- public MemoryHandle(IRetainable retainable, void* pointer = null, GCHandle handle = default(GCHandle))
+ public MemoryHandle(void* pointer, GCHandle handle = default, IPinnable pinnable = default)
{
- _retainable = retainable;
_pointer = pointer;
_handle = handle;
+ _pinnable = pinnable;
}
/// <summary>
- /// Returns the pointer to memory, or null if a pointer was not provided when the handle was created.
+ /// Returns the pointer to memory, where the memory is assumed to be pinned and hence the address won't change.
/// </summary>
[CLSCompliant(false)]
public void* Pointer => _pointer;
/// <summary>
- /// Returns false if the pointer to memory is null.
+ /// Frees the pinned handle and releases IPinnable.
/// </summary>
- public bool HasPointer => _pointer != null;
-
- /// <summary>
- /// Frees the pinned handle and releases IRetainable.
- /// </summary>
- public void Dispose()
+ public void Dispose()
{
if (_handle.IsAllocated)
{
_handle.Free();
}
- if (_retainable != null)
+ if (_pinnable != null)
{
- _retainable.Release();
- _retainable = null;
+ _pinnable.Unpin();
+ _pinnable = null;
}
_pointer = null;
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs b/src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs
new file mode 100644
index 000000000..1b235b538
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs
@@ -0,0 +1,75 @@
+// 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.Runtime.CompilerServices;
+
+namespace System.Buffers
+{
+ /// <summary>
+ /// Manager of <see cref="System.Memory{T}"/> that provides the implementation.
+ /// </summary>
+ public abstract class MemoryManager<T> : IMemoryOwner<T>, IPinnable
+ {
+ /// <summary>
+ /// Returns a <see cref="System.Memory{T}"/>.
+ /// </summary>
+ public virtual Memory<T> Memory => new Memory<T>(this, GetSpan().Length);
+
+ /// <summary>
+ /// Returns a span wrapping the underlying memory.
+ /// </summary>
+ public abstract Span<T> GetSpan();
+
+ /// <summary>
+ /// Returns a handle to the memory that has been pinned and hence its address can be taken.
+ /// </summary>
+ /// <param name="elementIndex">The offset to the element within the memory at which the returned <see cref="MemoryHandle"/> points to. (default = 0)</param>
+ public abstract MemoryHandle Pin(int elementIndex = 0);
+
+ /// <summary>
+ /// Lets the garbage collector know that the object is free to be moved now.
+ /// </summary>
+ public abstract void Unpin();
+
+ /// <summary>
+ /// Returns a <see cref="System.Memory{T}"/> for the current <see cref="MemoryManager{T}"/>.
+ /// </summary>
+ /// <param name="length">The element count in the memory, starting at offset 0.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected Memory<T> CreateMemory(int length) => new Memory<T>(this, length);
+
+ /// <summary>
+ /// Returns a <see cref="System.Memory{T}"/> for the current <see cref="MemoryManager{T}"/>.
+ /// </summary>
+ /// <param name="start">The offset to the element which the returned memory starts at.</param>
+ /// <param name="length">The element count in the memory, starting at element offset <paramref name="start"/>.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected Memory<T> CreateMemory(int start, int length) => new Memory<T>(this, start, length);
+
+ /// <summary>
+ /// Returns an array segment.
+ /// <remarks>Returns the default array segment if not overriden.</remarks>
+ /// </summary>
+ protected internal virtual bool TryGetArray(out ArraySegment<T> segment)
+ {
+ segment = default;
+ return false;
+ }
+
+ /// <summary>
+ /// Implements IDisposable.
+ /// </summary>
+ void IDisposable.Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Clean up of any leftover managed and unmanaged resources.
+ /// </summary>
+ protected abstract void Dispose(bool disposing);
+
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs b/src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs
deleted file mode 100644
index eade1feff..000000000
--- a/src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-// 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.Runtime;
-using System.Runtime.CompilerServices;
-
-namespace System.Buffers
-{
- /// <summary>
- /// Owner of Memory<typeparamref name="T"/> that provides appropriate lifetime management mechanisms for it.
- /// </summary>
- public abstract class OwnedMemory<T> : IDisposable, IRetainable
- {
- /// <summary>
- /// The number of items in the Memory<typeparamref name="T"/>.
- /// </summary>
- public abstract int Length { get; }
-
- /// <summary>
- /// Returns a span wrapping the underlying memory.
- /// </summary>
- public abstract Span<T> Span { get; }
-
- /// <summary>
- /// Returns a Memory<typeparamref name="T"/> if the underlying memory has not been freed.
- /// </summary>
- /// <exception cref="System.ObjectDisposedException">
- /// Thrown when the underlying memory has already been disposed.
- /// </exception>
- public Memory<T> Memory
- {
- get
- {
- if (IsDisposed)
- {
- ThrowHelper.ThrowObjectDisposedException_MemoryDisposed();
- }
- return new Memory<T>(owner: this, 0, Length);
- }
- }
-
- /// <summary>
- /// Returns a handle for the array that has been pinned and hence its address can be taken
- /// </summary>
- public abstract MemoryHandle Pin(int byteOffset = 0);
-
- /// <summary>
- /// Returns an array segment.
- /// </summary>
- protected internal abstract bool TryGetArray(out ArraySegment<T> arraySegment);
-
- /// <summary>
- /// Implements IDisposable.
- /// </summary>
- /// <exception cref="System.InvalidOperationException">
- /// Throw when there are still retained references to the memory
- /// </exception>
- public void Dispose()
- {
- if (IsRetained)
- {
- ThrowHelper.ThrowInvalidOperationException_OutstandingReferences();
- }
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Clean up of any leftover managed and unmanaged resources.
- /// </summary>
- protected abstract void Dispose(bool disposing);
-
- /// <summary>
- /// Return true if someone is holding a reference to the memory.
- /// </summary>
- protected abstract bool IsRetained { get; }
-
- /// <summary>
- /// Return true if the underlying memory has been freed.
- /// </summary>
- public abstract bool IsDisposed { get; }
-
- /// <summary>
- /// Implements IRetainable. Prevent accidental disposal of the memory.
- /// </summary>
- public abstract void Retain();
-
- /// <summary>
- /// Implements IRetainable. The memory can now be diposed.
- /// </summary>
- public abstract bool Release();
-
- }
-}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs
new file mode 100644
index 000000000..b6140adba
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs
@@ -0,0 +1,161 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Buffers.Text
+{
+ internal static partial class FormattingHelpers
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountDigits(ulong value)
+ {
+ int digits = 1;
+ uint part;
+ if (value >= 10000000)
+ {
+ if (value >= 100000000000000)
+ {
+ part = (uint)(value / 100000000000000);
+ digits += 14;
+ }
+ else
+ {
+ part = (uint)(value / 10000000);
+ digits += 7;
+ }
+ }
+ else
+ {
+ part = (uint)value;
+ }
+
+ if (part < 10)
+ {
+ // no-op
+ }
+ else if (part < 100)
+ {
+ digits += 1;
+ }
+ else if (part < 1000)
+ {
+ digits += 2;
+ }
+ else if (part < 10000)
+ {
+ digits += 3;
+ }
+ else if (part < 100000)
+ {
+ digits += 4;
+ }
+ else if (part < 1000000)
+ {
+ digits += 5;
+ }
+ else
+ {
+ Debug.Assert(part < 10000000);
+ digits += 6;
+ }
+
+ return digits;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountDigits(uint value)
+ {
+ int digits = 1;
+ if (value >= 100000)
+ {
+ value = value / 100000;
+ digits += 5;
+ }
+
+ if (value < 10)
+ {
+ // no-op
+ }
+ else if (value < 100)
+ {
+ digits += 1;
+ }
+ else if (value < 1000)
+ {
+ digits += 2;
+ }
+ else if (value < 10000)
+ {
+ digits += 3;
+ }
+ else
+ {
+ Debug.Assert(value < 100000);
+ digits += 4;
+ }
+
+ return digits;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountHexDigits(ulong value)
+ {
+ // TODO: When x86 intrinsic support comes online, experiment with implementing this using lzcnt.
+ // return 16 - (int)((uint)Lzcnt.LeadingZeroCount(value | 1) >> 3);
+
+ int digits = 1;
+
+ if (value > 0xFFFFFFFF)
+ {
+ digits += 8;
+ value >>= 0x20;
+ }
+ if (value > 0xFFFF)
+ {
+ digits += 4;
+ value >>= 0x10;
+ }
+ if (value > 0xFF)
+ {
+ digits += 2;
+ value >>= 0x8;
+ }
+ if (value > 0xF)
+ digits++;
+
+ return digits;
+ }
+
+
+ // Counts the number of trailing '0' digits in a decimal number.
+ // e.g., value = 0 => retVal = 0, valueWithoutTrailingZeros = 0
+ // value = 1234 => retVal = 0, valueWithoutTrailingZeros = 1234
+ // value = 320900 => retVal = 2, valueWithoutTrailingZeros = 3209
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountDecimalTrailingZeros(uint value, out uint valueWithoutTrailingZeros)
+ {
+ int zeroCount = 0;
+
+ if (value != 0)
+ {
+ while (true)
+ {
+ uint temp = value / 10;
+ if (value != (temp * 10))
+ {
+ break;
+ }
+
+ value = temp;
+ zeroCount++;
+ }
+ }
+
+ valueWithoutTrailingZeros = value;
+ return zeroCount;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
index 64c5cebe8..96efb0d52 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
@@ -2,9 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
+using Internal.Runtime.Augments;
+using Internal.Runtime.CompilerServices;
namespace System.Buffers
{
@@ -22,7 +25,6 @@ namespace System.Buffers
{
// TODO: #7747: "Investigate optimizing ArrayPool heuristics"
// - Explore caching in TLS more than one array per size per thread, and moving stale buffers to the global queue.
- // - Explore dumping stale buffers from the global queue, similar to PinnableBufferCache (maybe merging them).
// - Explore changing the size of each per-core bucket, potentially dynamically or based on other factors like array size.
// - Explore changing number of buckets and what sizes of arrays are cached.
// - Investigate whether false sharing is causing any issues, in particular on LockedStack's count and the contents of its array.
@@ -46,6 +48,15 @@ namespace System.Buffers
[ThreadStatic]
private static T[][] t_tlsBuckets;
+ private int _callbackCreated;
+
+ private readonly static bool s_trimBuffers = GetTrimBuffers();
+
+ /// <summary>
+ /// Used to keep track of all thread local buckets for trimming if needed
+ /// </summary>
+ private static readonly ConditionalWeakTable<T[][], object> s_allTlsBuckets = s_trimBuffers ? new ConditionalWeakTable<T[][], object>() : null;
+
/// <summary>Initialize the pool.</summary>
public TlsOverPerCoreLockedStacksArrayPool()
{
@@ -180,15 +191,24 @@ namespace System.Buffers
{
t_tlsBuckets = tlsBuckets = new T[NumBuckets][];
tlsBuckets[bucketIndex] = array;
+ if (s_trimBuffers)
+ {
+ s_allTlsBuckets.Add(tlsBuckets, null);
+ if (Interlocked.Exchange(ref _callbackCreated, 1) != 1)
+ {
+ Gen2GcCallback.Register(Gen2GcCallbackFunc, this);
+ }
+ }
}
else
{
T[] prev = tlsBuckets[bucketIndex];
tlsBuckets[bucketIndex] = array;
+
if (prev != null)
{
- PerCoreLockedStacks bucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex);
- bucket.TryPush(prev);
+ PerCoreLockedStacks stackBucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex);
+ stackBucket.TryPush(prev);
}
}
}
@@ -201,6 +221,103 @@ namespace System.Buffers
}
}
+ public bool Trim()
+ {
+ int milliseconds = Environment.TickCount;
+ MemoryPressure pressure = GetMemoryPressure();
+
+ ArrayPoolEventSource log = ArrayPoolEventSource.Log;
+ if (log.IsEnabled())
+ log.BufferTrimPoll(milliseconds, (int)pressure);
+
+ foreach (PerCoreLockedStacks bucket in _buckets)
+ {
+ bucket?.Trim((uint)milliseconds, Id, pressure, _bucketArraySizes);
+ }
+
+ if (pressure == MemoryPressure.High)
+ {
+ // Under high pressure, release all thread locals
+ if (log.IsEnabled())
+ {
+ foreach (KeyValuePair<T[][], object> tlsBuckets in s_allTlsBuckets)
+ {
+ T[][] buckets = tlsBuckets.Key;
+ for (int i = 0; i < buckets.Length; i++)
+ {
+ T[] buffer = Interlocked.Exchange(ref buckets[i], null);
+ if (buffer != null)
+ {
+ // As we don't want to take a perf hit in the rent path it
+ // is possible that a buffer could be rented as we "free" it.
+ log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id);
+ }
+ }
+ }
+ }
+ else
+ {
+ foreach (KeyValuePair<T[][], object> tlsBuckets in s_allTlsBuckets)
+ {
+ T[][] buckets = tlsBuckets.Key;
+ Array.Clear(buckets, 0, buckets.Length);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// This is the static function that is called from the gen2 GC callback.
+ /// The input object is the instance we want the callback on.
+ /// </summary>
+ /// <remarks>
+ /// The reason that we make this function static and take the instance as a parameter is that
+ /// we would otherwise root the instance to the Gen2GcCallback object, leaking the instance even when
+ /// the application no longer needs it.
+ /// </remarks>
+ private static bool Gen2GcCallbackFunc(object target)
+ {
+ return ((TlsOverPerCoreLockedStacksArrayPool<T>)(target)).Trim();
+ }
+
+ private enum MemoryPressure
+ {
+ Low,
+ Medium,
+ High
+ }
+
+ private static MemoryPressure GetMemoryPressure()
+ {
+ const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high"
+ const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium"
+
+ GC.GetMemoryInfo(out uint threshold, out _, out uint lastLoad, out _, out _);
+ if (lastLoad >= threshold * HighPressureThreshold)
+ {
+ return MemoryPressure.High;
+ }
+ else if (lastLoad >= threshold * MediumPressureThreshold)
+ {
+ return MemoryPressure.Medium;
+ }
+ return MemoryPressure.Low;
+ }
+
+ private static bool GetTrimBuffers()
+ {
+ // Environment uses ArrayPool, so we have to hit the API directly.
+#if !CORECLR
+ // P/Invokes are different for CoreCLR/RT- for RT we'll not allow
+ // enabling/disabling for now.
+ return true;
+#else
+ return CLRConfig.GetBoolValueWithFallbacks("System.Buffers.ArrayPool.TrimShared", "DOTNET_SYSTEM_BUFFERS_ARRAYPOOL_TRIMSHARED", defaultValue: true);
+#endif
+ }
+
/// <summary>
/// Stores a set of stacks of arrays, with one stack per core.
/// </summary>
@@ -228,7 +345,7 @@ namespace System.Buffers
// Try to push on to the associated stack first. If that fails,
// round-robin through the other stacks.
LockedStack[] stacks = _perCoreStacks;
- int index = Environment.CurrentExecutionId % stacks.Length;
+ int index = RuntimeThread.GetCurrentProcessorId() % stacks.Length;
for (int i = 0; i < stacks.Length; i++)
{
if (stacks[index].TryPush(array)) return;
@@ -244,7 +361,7 @@ namespace System.Buffers
// round-robin through the other stacks.
T[] arr;
LockedStack[] stacks = _perCoreStacks;
- int index = Environment.CurrentExecutionId % stacks.Length;
+ int index = RuntimeThread.GetCurrentProcessorId() % stacks.Length;
for (int i = 0; i < stacks.Length; i++)
{
if ((arr = stacks[index].TryPop()) != null) return arr;
@@ -252,6 +369,16 @@ namespace System.Buffers
}
return null;
}
+
+ public bool Trim(uint tickCount, int id, MemoryPressure pressure, int[] bucketSizes)
+ {
+ LockedStack[] stacks = _perCoreStacks;
+ for (int i = 0; i < stacks.Length; i++)
+ {
+ stacks[i].Trim(tickCount, id, pressure, bucketSizes[i]);
+ }
+ return true;
+ }
}
/// <summary>Provides a simple stack of arrays, protected by a lock.</summary>
@@ -259,6 +386,7 @@ namespace System.Buffers
{
private readonly T[][] _arrays = new T[MaxBuffersPerArraySizePerCore][];
private int _count;
+ private uint _firstStackItemMS;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPush(T[] array)
@@ -267,6 +395,12 @@ namespace System.Buffers
Monitor.Enter(this);
if (_count < MaxBuffersPerArraySizePerCore)
{
+ if (s_trimBuffers && _count == 0)
+ {
+ // Stash the time the bottom of the stack was filled
+ _firstStackItemMS = (uint)Environment.TickCount;
+ }
+
_arrays[_count++] = array;
enqueued = true;
}
@@ -287,6 +421,76 @@ namespace System.Buffers
Monitor.Exit(this);
return arr;
}
+
+ public void Trim(uint tickCount, int id, MemoryPressure pressure, int bucketSize)
+ {
+ const uint StackTrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure
+ const uint StackHighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure
+ const uint StackRefreshMS = StackTrimAfterMS / 4; // Time bump after trimming (1/4 trim time)
+ const int StackLowTrimCount = 1; // Trim one item when pressure is low
+ const int StackMediumTrimCount = 2; // Trim two items when pressure is moderate
+ const int StackHighTrimCount = MaxBuffersPerArraySizePerCore; // Trim all items when pressure is high
+ const int StackLargeBucket = 16384; // If the bucket is larger than this we'll trim an extra when under high pressure
+ const int StackModerateTypeSize = 16; // If T is larger than this we'll trim an extra when under high pressure
+ const int StackLargeTypeSize = 32; // If T is larger than this we'll trim an extra (additional) when under high pressure
+
+ if (_count == 0)
+ return;
+ uint trimTicks = pressure == MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS;
+
+ lock (this)
+ {
+ if (_count > 0 && _firstStackItemMS > tickCount || (tickCount - _firstStackItemMS) > trimTicks)
+ {
+ // We've wrapped the tick count or elapsed enough time since the
+ // first item went into the stack. Drop the top item so it can
+ // be collected and make the stack look a little newer.
+
+ ArrayPoolEventSource log = ArrayPoolEventSource.Log;
+ int trimCount = StackLowTrimCount;
+ switch (pressure)
+ {
+ case MemoryPressure.High:
+ trimCount = StackHighTrimCount;
+
+ // When pressure is high, aggressively trim larger arrays.
+ if (bucketSize > StackLargeBucket)
+ {
+ trimCount++;
+ }
+ if (Unsafe.SizeOf<T>() > StackModerateTypeSize)
+ {
+ trimCount++;
+ }
+ if (Unsafe.SizeOf<T>() > StackLargeTypeSize)
+ {
+ trimCount++;
+ }
+ break;
+ case MemoryPressure.Medium:
+ trimCount = StackMediumTrimCount;
+ break;
+ }
+
+ while (_count > 0 && trimCount-- > 0)
+ {
+ T[] array = _arrays[--_count];
+ _arrays[_count] = null;
+
+ if (log.IsEnabled())
+ {
+ log.BufferTrimmed(array.GetHashCode(), array.Length, id);
+ }
+ }
+
+ if (_count > 0 && _firstStackItemMS < uint.MaxValue - StackRefreshMS)
+ {
+ // Give the remaining items a bit more time
+ _firstStackItemMS += StackRefreshMS;
+ }
+ }
+ }
+ }
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs b/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs
index 4f115fe9d..b675100b0 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs
@@ -12,14 +12,19 @@ namespace System.Buffers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int SelectBucketIndex(int bufferSize)
{
+ Debug.Assert(bufferSize >= 0);
+
+ // bufferSize of 0 will underflow here, causing a huge
+ // index which the caller will discard because it is not
+ // within the bounds of the bucket array.
uint bitsRemaining = ((uint)bufferSize - 1) >> 4;
int poolIndex = 0;
if (bitsRemaining > 0xFFFF) { bitsRemaining >>= 16; poolIndex = 16; }
- if (bitsRemaining > 0xFF) { bitsRemaining >>= 8; poolIndex += 8; }
- if (bitsRemaining > 0xF) { bitsRemaining >>= 4; poolIndex += 4; }
- if (bitsRemaining > 0x3) { bitsRemaining >>= 2; poolIndex += 2; }
- if (bitsRemaining > 0x1) { bitsRemaining >>= 1; poolIndex += 1; }
+ if (bitsRemaining > 0xFF) { bitsRemaining >>= 8; poolIndex += 8; }
+ if (bitsRemaining > 0xF) { bitsRemaining >>= 4; poolIndex += 4; }
+ if (bitsRemaining > 0x3) { bitsRemaining >>= 2; poolIndex += 2; }
+ if (bitsRemaining > 0x1) { bitsRemaining >>= 1; poolIndex += 1; }
return poolIndex + (int)bitsRemaining;
}
diff --git a/src/System.Private.CoreLib/shared/System/Byte.cs b/src/System.Private.CoreLib/shared/System/Byte.cs
index 13ceb7573..da1f9147b 100644
--- a/src/System.Private.CoreLib/shared/System/Byte.cs
+++ b/src/System.Private.CoreLib/shared/System/Byte.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Byte : IComparable, IConvertible, IFormattable, IComparable<Byte>, IEquatable<Byte>, ISpanFormattable
+ public readonly struct Byte : IComparable, IConvertible, IFormattable, IComparable<byte>, IEquatable<byte>, ISpanFormattable
{
- private byte m_value; // Do not rename (binary serialization)
+ private readonly byte m_value; // Do not rename (binary serialization)
// The maximum value that a Byte may represent: 255.
public const byte MaxValue = (byte)0xFF;
@@ -29,37 +29,37 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type byte, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (!(value is Byte))
+ if (!(value is byte))
{
throw new ArgumentException(SR.Arg_MustBeByte);
}
- return m_value - (((Byte)value).m_value);
+ return m_value - (((byte)value).m_value);
}
- public int CompareTo(Byte value)
+ public int CompareTo(byte value)
{
return m_value - value;
}
// Determines whether two Byte objects are equal.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Byte))
+ if (!(obj is byte))
{
return false;
}
- return m_value == ((Byte)obj).m_value;
+ return m_value == ((byte)obj).m_value;
}
[NonVersionable]
- public bool Equals(Byte obj)
+ public bool Equals(byte obj)
{
return m_value == obj;
}
@@ -70,20 +70,20 @@ namespace System
return m_value;
}
- public static byte Parse(String s)
+ public static byte Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static byte Parse(String s, NumberStyles style)
+ public static byte Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, style, NumberFormatInfo.CurrentInfo);
}
- public static byte Parse(String s, IFormatProvider provider)
+ public static byte Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -92,7 +92,7 @@ namespace System
// Parses an unsigned byte from a String in the given style. If
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
- public static byte Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static byte Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -121,7 +121,7 @@ namespace System
return (byte)i;
}
- public static bool TryParse(String s, out Byte result)
+ public static bool TryParse(string s, out byte result)
{
if (s == null)
{
@@ -137,7 +137,7 @@ namespace System
return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Byte result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out byte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -156,7 +156,7 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Byte result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out byte result)
{
result = 0;
int i;
@@ -172,33 +172,29 @@ namespace System
return true;
}
- public override String ToString()
+ public override string ToString()
{
- return Number.FormatInt32(m_value, null, null);
+ return Number.FormatUInt32(m_value, null, null);
}
- public String ToString(String format)
+ public string ToString(string format)
{
- return Number.FormatInt32(m_value, format, null);
+ return Number.FormatUInt32(m_value, format, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
- return Number.FormatInt32(m_value, null, provider);
+ return Number.FormatUInt32(m_value, null, provider);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
- return Number.FormatInt32(m_value, format, provider);
+ return Number.FormatUInt32(m_value, format, provider);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public bool TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider) =>
- TryFormat(destination, out charsWritten, (ReadOnlySpan<char>)format, provider);
-
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null)
{
- return Number.TryFormatInt32(m_value, format, provider, destination, out charsWritten);
+ return Number.TryFormatUInt32(m_value, format, provider, destination, out charsWritten);
}
//
@@ -270,7 +266,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -280,7 +276,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Byte", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Char.cs b/src/System.Private.CoreLib/shared/System/Char.cs
index d3ed1f5b6..8c743369b 100644
--- a/src/System.Private.CoreLib/shared/System/Char.cs
+++ b/src/System.Private.CoreLib/shared/System/Char.cs
@@ -21,12 +21,12 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Char : IComparable, IComparable<Char>, IEquatable<Char>, IConvertible
+ public readonly struct Char : IComparable, IComparable<char>, IEquatable<char>, IConvertible
{
//
// Member Variables
//
- private char m_value; // Do not rename (binary serialization)
+ private readonly char m_value; // Do not rename (binary serialization)
//
// Public Constants
@@ -87,7 +87,7 @@ namespace System
// Return the Unicode category for Unicode character <= 0x00ff.
private static UnicodeCategory GetLatin1UnicodeCategory(char ch)
{
- Debug.Assert(IsLatin1(ch), "Char.GetLatin1UnicodeCategory(): ch should be <= 007f");
+ Debug.Assert(IsLatin1(ch), "char.GetLatin1UnicodeCategory(): ch should be <= 007f");
return (UnicodeCategory)(s_categoryForLatin1[(int)ch]);
}
@@ -107,17 +107,17 @@ namespace System
// Used for comparing two boxed Char objects.
//
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Char))
+ if (!(obj is char))
{
return false;
}
- return (m_value == ((Char)obj).m_value);
+ return (m_value == ((char)obj).m_value);
}
[System.Runtime.Versioning.NonVersionable]
- public bool Equals(Char obj)
+ public bool Equals(char obj)
{
return m_value == obj;
}
@@ -128,34 +128,34 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Char, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (!(value is Char))
+ if (!(value is char))
{
throw new ArgumentException(SR.Arg_MustBeChar);
}
- return (m_value - ((Char)value).m_value);
+ return (m_value - ((char)value).m_value);
}
- public int CompareTo(Char value)
+ public int CompareTo(char value)
{
return (m_value - value);
}
// Overrides System.Object.ToString.
- public override String ToString()
+ public override string ToString()
{
- return Char.ToString(m_value);
+ return char.ToString(m_value);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
- return Char.ToString(m_value);
+ return char.ToString(m_value);
}
//
@@ -168,7 +168,7 @@ namespace System
// Provides a string representation of a character.
public static string ToString(char c) => string.CreateFromChar(c);
- public static char Parse(String s)
+ public static char Parse(string s)
{
if (s == null)
{
@@ -182,7 +182,7 @@ namespace System
return s[0];
}
- public static bool TryParse(String s, out Char result)
+ public static bool TryParse(string s, out char result)
{
result = '\0';
if (s == null)
@@ -201,7 +201,7 @@ namespace System
// Static Methods
//
/*=================================ISDIGIT======================================
- **A wrapper for Char. Returns a boolean indicating whether **
+ **A wrapper for char. Returns a boolean indicating whether **
**character c is considered to be a digit. **
==============================================================================*/
// Determines whether a character is a digit.
@@ -233,7 +233,7 @@ namespace System
}
/*=================================ISLETTER=====================================
- **A wrapper for Char. Returns a boolean indicating whether **
+ **A wrapper for char. Returns a boolean indicating whether **
**character c is considered to be a letter. **
==============================================================================*/
// Determines whether a character is a letter.
@@ -271,7 +271,7 @@ namespace System
}
/*===============================ISWHITESPACE===================================
- **A wrapper for Char. Returns a boolean indicating whether **
+ **A wrapper for char. Returns a boolean indicating whether **
**character c is considered to be a whitespace character. **
==============================================================================*/
// Determines whether a character is whitespace.
@@ -393,7 +393,7 @@ namespace System
}
/*=================================TOUPPER======================================
- **A wrapper for Char.toUpperCase. Converts character c to its **
+ **A wrapper for char.ToUpperCase. Converts character c to its **
**uppercase equivalent. If c is already an uppercase character or is not an **
**alphabetic, nothing happens. **
==============================================================================*/
@@ -425,7 +425,7 @@ namespace System
}
/*=================================TOLOWER======================================
- **A wrapper for Char.toLowerCase. Converts character c to its **
+ **A wrapper for char.ToLowerCase. Converts character c to its **
**lowercase equivalent. If c is already a lowercase character or is not an **
**alphabetic, nothing happens. **
==============================================================================*/
@@ -512,7 +512,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Char", "Double"));
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Char", "Decimal"));
}
@@ -522,7 +522,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Char", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
@@ -535,7 +535,7 @@ namespace System
return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Control);
}
- public static bool IsControl(String s, int index)
+ public static bool IsControl(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -552,7 +552,7 @@ namespace System
}
- public static bool IsDigit(String s, int index)
+ public static bool IsDigit(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -568,7 +568,7 @@ namespace System
return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.DecimalDigitNumber);
}
- public static bool IsLetter(String s, int index)
+ public static bool IsLetter(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -589,7 +589,7 @@ namespace System
return (CheckLetter(CharUnicodeInfo.GetUnicodeCategory(s, index)));
}
- public static bool IsLetterOrDigit(String s, int index)
+ public static bool IsLetterOrDigit(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -605,7 +605,7 @@ namespace System
return CheckLetterOrDigit(CharUnicodeInfo.GetUnicodeCategory(s, index));
}
- public static bool IsLower(String s, int index)
+ public static bool IsLower(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -655,7 +655,7 @@ namespace System
return (CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c)));
}
- public static bool IsNumber(String s, int index)
+ public static bool IsNumber(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -683,7 +683,7 @@ namespace System
//
////////////////////////////////////////////////////////////////////////
- public static bool IsPunctuation(String s, int index)
+ public static bool IsPunctuation(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -732,7 +732,7 @@ namespace System
return (CheckSeparator(CharUnicodeInfo.GetUnicodeCategory(c)));
}
- public static bool IsSeparator(String s, int index)
+ public static bool IsSeparator(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -753,7 +753,7 @@ namespace System
return (c >= HIGH_SURROGATE_START && c <= LOW_SURROGATE_END);
}
- public static bool IsSurrogate(String s, int index)
+ public static bool IsSurrogate(string s, int index)
{
if (s == null)
{
@@ -792,7 +792,7 @@ namespace System
return (CheckSymbol(CharUnicodeInfo.GetUnicodeCategory(c)));
}
- public static bool IsSymbol(String s, int index)
+ public static bool IsSymbol(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -809,7 +809,7 @@ namespace System
}
- public static bool IsUpper(String s, int index)
+ public static bool IsUpper(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -830,7 +830,7 @@ namespace System
return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.UppercaseLetter);
}
- public static bool IsWhiteSpace(String s, int index)
+ public static bool IsWhiteSpace(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -856,7 +856,7 @@ namespace System
return CharUnicodeInfo.GetUnicodeCategory((int)c);
}
- public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ public static UnicodeCategory GetUnicodeCategory(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -876,7 +876,7 @@ namespace System
return CharUnicodeInfo.GetNumericValue(c);
}
- public static double GetNumericValue(String s, int index)
+ public static double GetNumericValue(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -896,7 +896,7 @@ namespace System
return ((c >= CharUnicodeInfo.HIGH_SURROGATE_START) && (c <= CharUnicodeInfo.HIGH_SURROGATE_END));
}
- public static bool IsHighSurrogate(String s, int index)
+ public static bool IsHighSurrogate(string s, int index)
{
if (s == null)
{
@@ -917,7 +917,7 @@ namespace System
return ((c >= CharUnicodeInfo.LOW_SURROGATE_START) && (c <= CharUnicodeInfo.LOW_SURROGATE_END));
}
- public static bool IsLowSurrogate(String s, int index)
+ public static bool IsLowSurrogate(string s, int index)
{
if (s == null)
{
@@ -933,7 +933,7 @@ namespace System
/*================================= IsSurrogatePair ============================
** Check if the string specified by the index starts with a surrogate pair.
==============================================================================*/
- public static bool IsSurrogatePair(String s, int index)
+ public static bool IsSurrogatePair(string s, int index)
{
if (s == null)
{
@@ -972,7 +972,7 @@ namespace System
** Convert an UTF32 value into a surrogate pair.
==============================================================================*/
- public static String ConvertFromUtf32(int utf32)
+ public static string ConvertFromUtf32(int utf32)
{
// For UTF32 values from U+00D800 ~ U+00DFFF, we should throw. They
// are considered as irregular code unit sequence, but they are not illegal.
@@ -984,7 +984,7 @@ namespace System
if (utf32 < UNICODE_PLANE01_START)
{
// This is a BMP character.
- return (Char.ToString((char)utf32));
+ return (char.ToString((char)utf32));
}
unsafe
@@ -1025,7 +1025,7 @@ namespace System
** This method throws if a low surrogate is seen without preceding a high-surrogate.
==============================================================================*/
- public static int ConvertToUtf32(String s, int index)
+ public static int ConvertToUtf32(string s, int index)
{
if (s == null)
{
diff --git a/src/System.Private.CoreLib/shared/System/CharEnumerator.cs b/src/System.Private.CoreLib/shared/System/CharEnumerator.cs
index ea9915a7c..ca60705d9 100644
--- a/src/System.Private.CoreLib/shared/System/CharEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/CharEnumerator.cs
@@ -19,11 +19,11 @@ namespace System
{
public sealed class CharEnumerator : IEnumerator, IEnumerator<char>, IDisposable, ICloneable
{
- private String _str;
+ private string _str;
private int _index;
private char _currentElement;
- internal CharEnumerator(String str)
+ internal CharEnumerator(string str)
{
_str = str;
_index = -1;
@@ -54,7 +54,7 @@ namespace System
_str = null;
}
- Object IEnumerator.Current
+ object IEnumerator.Current
{
get { return Current; }
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs b/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs
index 6fcedc09a..e22fb5bb9 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs
@@ -52,7 +52,7 @@ namespace System.Collections
// If a doesn't implement IComparable and b does, -(b.CompareTo(a)) is returned.
// Otherwise an exception is thrown.
//
- public int Compare(Object a, Object b)
+ public int Compare(object a, object b)
{
if (a == b) return 0;
if (a == null) return -1;
diff --git a/src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs
new file mode 100644
index 000000000..587fd6839
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs
@@ -0,0 +1,61 @@
+// 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.
+
+#pragma warning disable 618 // obsolete types
+
+namespace System.Collections
+{
+ internal sealed class CompatibleComparer : IEqualityComparer
+ {
+ private readonly IHashCodeProvider _hcp;
+ private readonly IComparer _comparer;
+
+ internal CompatibleComparer(IHashCodeProvider hashCodeProvider, IComparer comparer)
+ {
+ _hcp = hashCodeProvider;
+ _comparer = comparer;
+ }
+
+ internal IHashCodeProvider HashCodeProvider => _hcp;
+
+ internal IComparer Comparer => _comparer;
+
+ public new bool Equals(object a, object b) => Compare(a, b) == 0;
+
+ public int Compare(object a, object b)
+ {
+ if (a == b)
+ return 0;
+ if (a == null)
+ return -1;
+ if (b == null)
+ return 1;
+
+ if (_comparer != null)
+ {
+ return _comparer.Compare(a, b);
+ }
+
+ IComparable ia = a as IComparable;
+ if (ia != null)
+ {
+ return ia.CompareTo(b);
+ }
+
+ throw new ArgumentException(SR.Argument_ImplementIComparable);
+ }
+
+ public int GetHashCode(object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ return _hcp != null ?
+ _hcp.GetHashCode(obj) :
+ obj.GetHashCode();
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs
new file mode 100644
index 000000000..63880b09f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs
@@ -0,0 +1,834 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// Represents a thread-safe first-in, first-out collection of objects.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
+ /// <remarks>
+ /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </remarks>
+ [DebuggerDisplay("Count = {Count}")]
+ [DebuggerTypeProxy(typeof(IProducerConsumerCollectionDebugView<>))]
+ public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
+ {
+ // This implementation provides an unbounded, multi-producer multi-consumer queue
+ // that supports the standard Enqueue/TryDequeue operations, as well as support for
+ // snapshot enumeration (GetEnumerator, ToArray, CopyTo), peeking, and Count/IsEmpty.
+ // It is composed of a linked list of bounded ring buffers, each of which has a head
+ // and a tail index, isolated from each other to minimize false sharing. As long as
+ // the number of elements in the queue remains less than the size of the current
+ // buffer (Segment), no additional allocations are required for enqueued items. When
+ // the number of items exceeds the size of the current segment, the current segment is
+ // "frozen" to prevent further enqueues, and a new segment is linked from it and set
+ // as the new tail segment for subsequent enqueues. As old segments are consumed by
+ // dequeues, the head reference is updated to point to the segment that dequeuers should
+ // try next. To support snapshot enumeration, segments also support the notion of
+ // preserving for observation, whereby they avoid overwriting state as part of dequeues.
+ // Any operation that requires a snapshot results in all current segments being
+ // both frozen for enqueues and preserved for observation: any new enqueues will go
+ // to new segments, and dequeuers will consume from the existing segments but without
+ // overwriting the existing data.
+
+ /// <summary>Initial length of the segments used in the queue.</summary>
+ private const int InitialSegmentLength = 32;
+ /// <summary>
+ /// Maximum length of the segments used in the queue. This is a somewhat arbitrary limit:
+ /// larger means that as long as we don't exceed the size, we avoid allocating more segments,
+ /// but if we do exceed it, then the segment becomes garbage.
+ /// </summary>
+ private const int MaxSegmentLength = 1024 * 1024;
+
+ /// <summary>
+ /// Lock used to protect cross-segment operations, including any updates to <see cref="_tail"/> or <see cref="_head"/>
+ /// and any operations that need to get a consistent view of them.
+ /// </summary>
+ private object _crossSegmentLock;
+ /// <summary>The current tail segment.</summary>
+ private volatile ConcurrentQueueSegment<T> _tail;
+ /// <summary>The current head segment.</summary>
+ private volatile ConcurrentQueueSegment<T> _head;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class.
+ /// </summary>
+ public ConcurrentQueue()
+ {
+ _crossSegmentLock = new object();
+ _tail = _head = new ConcurrentQueueSegment<T>(InitialSegmentLength);
+ }
+
+ /// <summary>
+ /// Initializes the contents of the queue from an existing collection.
+ /// </summary>
+ /// <param name="collection">A collection from which to copy elements.</param>
+ private void InitializeFromCollection(IEnumerable<T> collection)
+ {
+ _crossSegmentLock = new object();
+
+ // Determine the initial segment size. We'll use the default,
+ // unless the collection is known to be larger than that, in which
+ // case we round its length up to a power of 2, as all segments must
+ // be a power of 2 in length.
+ int length = InitialSegmentLength;
+ var c = collection as ICollection<T>;
+ if (c != null)
+ {
+ int count = c.Count;
+ if (count > length)
+ {
+ length = Math.Min(ConcurrentQueueSegment<T>.RoundUpToPowerOf2(count), MaxSegmentLength);
+ }
+ }
+
+ // Initialize the segment and add all of the data to it.
+ _tail = _head = new ConcurrentQueueSegment<T>(length);
+ foreach (T item in collection)
+ {
+ Enqueue(item);
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class that contains elements copied
+ /// from the specified collection.
+ /// </summary>
+ /// <param name="collection">
+ /// The collection whose elements are copied to the new <see cref="ConcurrentQueue{T}"/>.
+ /// </param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="collection"/> argument is null.</exception>
+ public ConcurrentQueue(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+ }
+
+ InitializeFromCollection(collection);
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="ICollection"/> to an <see
+ /// cref="Array"/>, starting at a particular <see cref="Array"/> index.
+ /// </summary>
+ /// <param name="array">
+ /// The one-dimensional <see cref="Array">Array</see> that is the destination of the
+ /// elements copied from the <see cref="ConcurrentQueue{T}"/>. <paramref name="array"/> must have
+ /// zero-based indexing.
+ /// </param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="array"/> is multidimensional. -or-
+ /// <paramref name="array"/> does not have zero-based indexing. -or-
+ /// <paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ICollection"/> is
+ /// greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>. -or- The type of the source <see
+ /// cref="ICollection"/> cannot be cast automatically to the type of the
+ /// destination <paramref name="array"/>.
+ /// </exception>
+ void ICollection.CopyTo(Array array, int index)
+ {
+ // Special-case when the Array is actually a T[], taking a faster path
+ T[] szArray = array as T[];
+ if (szArray != null)
+ {
+ CopyTo(szArray, index);
+ return;
+ }
+
+ // Validate arguments.
+ if (array == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ // Otherwise, fall back to the slower path that first copies the contents
+ // to an array, and then uses that array's non-generic CopyTo to do the copy.
+ ToArray().CopyTo(array, index);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="ICollection"/> is
+ /// synchronized with the SyncRoot.
+ /// </summary>
+ /// <value>true if access to the <see cref="ICollection"/> is synchronized
+ /// with the SyncRoot; otherwise, false. For <see cref="ConcurrentQueue{T}"/>, this property always
+ /// returns false.</value>
+ bool ICollection.IsSynchronized => false; // always false, as true implies synchronization via SyncRoot
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see
+ /// cref="ICollection"/>. This property is not supported.
+ /// </summary>
+ /// <exception cref="NotSupportedException">The SyncRoot property is not supported.</exception>
+ object ICollection.SyncRoot { get { ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); return default; } }
+
+ /// <summary>Returns an enumerator that iterates through a collection.</summary>
+ /// <returns>An <see cref="IEnumerator"/> that can be used to iterate through the collection.</returns>
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>)this).GetEnumerator();
+
+ /// <summary>
+ /// Attempts to add an object to the <see cref="Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
+ /// reference (Nothing in Visual Basic) for reference types.
+ /// </param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will always add the object to the
+ /// end of the <see cref="ConcurrentQueue{T}"/>
+ /// and return true.</remarks>
+ bool IProducerConsumerCollection<T>.TryAdd(T item)
+ {
+ Enqueue(item);
+ return true;
+ }
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see cref="Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the operation was successful, <paramref name="item"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>true if an element was removed and returned successfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will attempt to remove the object
+ /// from the beginning of the <see cref="ConcurrentQueue{T}"/>.
+ /// </remarks>
+ bool IProducerConsumerCollection<T>.TryTake(out T item) => TryDequeue(out item);
+
+ /// <summary>
+ /// Gets a value that indicates whether the <see cref="ConcurrentQueue{T}"/> is empty.
+ /// </summary>
+ /// <value>true if the <see cref="ConcurrentQueue{T}"/> is empty; otherwise, false.</value>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of this property is recommended
+ /// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it
+ /// to 0. However, as this collection is intended to be accessed concurrently, it may be the case
+ /// that another thread will modify the collection after <see cref="IsEmpty"/> returns, thus invalidating
+ /// the result.
+ /// </remarks>
+ public bool IsEmpty
+ {
+ get
+ {
+ // IsEmpty == !TryPeek. We use a "resultUsed:false" peek in order to avoid marking
+ // segments as preserved for observation, making IsEmpty a cheaper way than either
+ // TryPeek(out T) or Count == 0 to check whether any elements are in the queue.
+ T ignoredResult;
+ return !TryPeek(out ignoredResult, resultUsed: false);
+ }
+ }
+
+ /// <summary>Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array.</summary>
+ /// <returns>A new array containing a snapshot of elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns>
+ public T[] ToArray()
+ {
+ // Snap the current contents for enumeration.
+ ConcurrentQueueSegment<T> head, tail;
+ int headHead, tailTail;
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
+
+ // Count the number of items in that snapped set, and use it to allocate an
+ // array of the right size.
+ long count = GetCount(head, headHead, tail, tailTail);
+ T[] arr = new T[count];
+
+ // Now enumerate the contents, copying each element into the array.
+ using (IEnumerator<T> e = Enumerate(head, headHead, tail, tailTail))
+ {
+ int i = 0;
+ while (e.MoveNext())
+ {
+ arr[i++] = e.Current;
+ }
+ Debug.Assert(count == i);
+ }
+
+ // And return it.
+ return arr;
+ }
+
+ /// <summary>
+ /// Gets the number of elements contained in the <see cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ /// <value>The number of elements contained in the <see cref="ConcurrentQueue{T}"/>.</value>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
+ /// property is recommended rather than retrieving the number of items from the <see cref="Count"/>
+ /// property and comparing it to 0.
+ /// </remarks>
+ public int Count
+ {
+ get
+ {
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Capture the head and tail, as well as the head's head and tail.
+ ConcurrentQueueSegment<T> head = _head;
+ ConcurrentQueueSegment<T> tail = _tail;
+ int headHead = Volatile.Read(ref head._headAndTail.Head);
+ int headTail = Volatile.Read(ref head._headAndTail.Tail);
+
+ if (head == tail)
+ {
+ // There was a single segment in the queue. If the captured segments still
+ // match, then we can trust the values to compute the segment's count. (It's
+ // theoretically possible the values could have looped around and still exactly match,
+ // but that would required at least ~4 billion elements to have been enqueued and
+ // dequeued between the reads.)
+ if (head == _head &&
+ tail == _tail &&
+ headHead == Volatile.Read(ref head._headAndTail.Head) &&
+ headTail == Volatile.Read(ref head._headAndTail.Tail))
+ {
+ return GetCount(head, headHead, headTail);
+ }
+ }
+ else if (head._nextSegment == tail)
+ {
+ // There were two segments in the queue. Get the positions from the tail, and as above,
+ // if the captured values match the previous reads, return the sum of the counts from both segments.
+ int tailHead = Volatile.Read(ref tail._headAndTail.Head);
+ int tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ if (head == _head &&
+ tail == _tail &&
+ headHead == Volatile.Read(ref head._headAndTail.Head) &&
+ headTail == Volatile.Read(ref head._headAndTail.Tail) &&
+ tailHead == Volatile.Read(ref tail._headAndTail.Head) &&
+ tailTail == Volatile.Read(ref tail._headAndTail.Tail))
+ {
+ return GetCount(head, headHead, headTail) + GetCount(tail, tailHead, tailTail);
+ }
+ }
+ else
+ {
+ // There were more than two segments in the queue. Fall back to taking the cross-segment lock,
+ // which will ensure that the head and tail segments we read are stable (since the lock is needed to change them);
+ // for the two-segment case above, we can simply rely on subsequent comparisons, but for the two+ case, we need
+ // to be able to trust the internal segments between the head and tail.
+ lock (_crossSegmentLock)
+ {
+ // Now that we hold the lock, re-read the previously captured head and tail segments and head positions.
+ // If either has changed, start over.
+ if (head == _head && tail == _tail)
+ {
+ // Get the positions from the tail, and as above, if the captured values match the previous reads,
+ // we can use the values to compute the count of the head and tail segments.
+ int tailHead = Volatile.Read(ref tail._headAndTail.Head);
+ int tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ if (headHead == Volatile.Read(ref head._headAndTail.Head) &&
+ headTail == Volatile.Read(ref head._headAndTail.Tail) &&
+ tailHead == Volatile.Read(ref tail._headAndTail.Head) &&
+ tailTail == Volatile.Read(ref tail._headAndTail.Tail))
+ {
+ // We got stable values for the head and tail segments, so we can just compute the sizes
+ // based on those and add them. Note that this and the below additions to count may overflow: previous
+ // implementations allowed that, so we don't check, either, and it is theoretically possible for the
+ // queue to store more than int.MaxValue items.
+ int count = GetCount(head, headHead, headTail) + GetCount(tail, tailHead, tailTail);
+
+ // Now add the counts for each internal segment. Since there were segments before these,
+ // for counting purposes we consider them to start at the 0th element, and since there is at
+ // least one segment after each, each was frozen, so we can count until each's frozen tail.
+ // With the cross-segment lock held, we're guaranteed that all of these internal segments are
+ // consistent, as the head and tail segment can't be changed while we're holding the lock, and
+ // dequeueing and enqueueing can only be done from the head and tail segments, which these aren't.
+ for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
+ {
+ Debug.Assert(s._frozenForEnqueues, "Internal segment must be frozen as there's a following segment.");
+ count += s._headAndTail.Tail - s.FreezeOffset;
+ }
+
+ return count;
+ }
+ }
+ }
+ }
+
+ // We raced with enqueues/dequeues and captured an inconsistent picture of the queue.
+ // Spin and try again.
+ spinner.SpinOnce();
+ }
+ }
+ }
+
+ /// <summary>Computes the number of items in a segment based on a fixed head and tail in that segment.</summary>
+ private static int GetCount(ConcurrentQueueSegment<T> s, int head, int tail)
+ {
+ if (head != tail && head != tail - s.FreezeOffset)
+ {
+ head &= s._slotsMask;
+ tail &= s._slotsMask;
+ return head < tail ? tail - head : s._slots.Length - head + tail;
+ }
+ return 0;
+ }
+
+ /// <summary>Gets the number of items in snapped region.</summary>
+ private static long GetCount(ConcurrentQueueSegment<T> head, int headHead, ConcurrentQueueSegment<T> tail, int tailTail)
+ {
+ // All of the segments should have been both frozen for enqueues and preserved for observation.
+ // Validate that here for head and tail; we'll validate it for intermediate segments later.
+ Debug.Assert(head._preservedForObservation);
+ Debug.Assert(head._frozenForEnqueues);
+ Debug.Assert(tail._preservedForObservation);
+ Debug.Assert(tail._frozenForEnqueues);
+
+ long count = 0;
+
+ // Head segment. We've already marked it as frozen for enqueues, so its tail position is fixed,
+ // and we've already marked it as preserved for observation (before we grabbed the head), so we
+ // can safely enumerate from its head to its tail and access its elements.
+ int headTail = (head == tail ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset;
+ if (headHead < headTail)
+ {
+ // Mask the head and tail for the head segment
+ headHead &= head._slotsMask;
+ headTail &= head._slotsMask;
+
+ // Increase the count by either the one or two regions, based on whether tail
+ // has wrapped to be less than head.
+ count += headHead < headTail ?
+ headTail - headHead :
+ head._slots.Length - headHead + headTail;
+ }
+
+ // We've enumerated the head. If the tail is different from the head, we need to
+ // enumerate the remaining segments.
+ if (head != tail)
+ {
+ // Count the contents of each segment between head and tail, not including head and tail.
+ // Since there were segments before these, for our purposes we consider them to start at
+ // the 0th element, and since there is at least one segment after each, each was frozen
+ // by the time we snapped it, so we can iterate until each's frozen tail.
+ for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
+ {
+ Debug.Assert(s._preservedForObservation);
+ Debug.Assert(s._frozenForEnqueues);
+ count += s._headAndTail.Tail - s.FreezeOffset;
+ }
+
+ // Finally, enumerate the tail. As with the intermediate segments, there were segments
+ // before this in the snapped region, so we can start counting from the beginning. Unlike
+ // the intermediate segments, we can't just go until the Tail, as that could still be changing;
+ // instead we need to go until the tail we snapped for observation.
+ count += tailTail - tail.FreezeOffset;
+ }
+
+ // Return the computed count.
+ return count;
+ }
+
+ /// <summary>
+ /// Copies the <see cref="ConcurrentQueue{T}"/> elements to an existing one-dimensional <see
+ /// cref="Array">Array</see>, starting at the specified array index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="Array">Array</see> that is the
+ /// destination of the elements copied from the
+ /// <see cref="ConcurrentQueue{T}"/>. The <see cref="Array">Array</see> must have zero-based
+ /// indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
+ /// length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
+ /// available space from <paramref name="index"/> to the end of the destination <paramref
+ /// name="array"/>.
+ /// </exception>
+ public void CopyTo(T[] array, int index)
+ {
+ if (array == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ if (index < 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ // Snap for enumeration
+ ConcurrentQueueSegment<T> head, tail;
+ int headHead, tailTail;
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
+
+ // Get the number of items to be enumerated
+ long count = GetCount(head, headHead, tail, tailTail);
+ if (index > array.Length - count)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ // Copy the items to the target array
+ int i = index;
+ using (IEnumerator<T> e = Enumerate(head, headHead, tail, tailTail))
+ {
+ while (e.MoveNext())
+ {
+ array[i++] = e.Current;
+ }
+ }
+ Debug.Assert(count == i - index);
+ }
+
+ /// <summary>Returns an enumerator that iterates through the <see cref="ConcurrentQueue{T}"/>.</summary>
+ /// <returns>An enumerator for the contents of the <see
+ /// cref="ConcurrentQueue{T}"/>.</returns>
+ /// <remarks>
+ /// The enumeration represents a moment-in-time snapshot of the contents
+ /// of the queue. It does not reflect any updates to the collection after
+ /// <see cref="GetEnumerator"/> was called. The enumerator is safe to use
+ /// concurrently with reads from and writes to the queue.
+ /// </remarks>
+ public IEnumerator<T> GetEnumerator()
+ {
+ ConcurrentQueueSegment<T> head, tail;
+ int headHead, tailTail;
+ SnapForObservation(out head, out headHead, out tail, out tailTail);
+ return Enumerate(head, headHead, tail, tailTail);
+ }
+
+ /// <summary>
+ /// Gets the head and tail information of the current contents of the queue.
+ /// After this call returns, the specified region can be enumerated any number
+ /// of times and will not change.
+ /// </summary>
+ private void SnapForObservation(out ConcurrentQueueSegment<T> head, out int headHead, out ConcurrentQueueSegment<T> tail, out int tailTail)
+ {
+ lock (_crossSegmentLock) // _head and _tail may only change while the lock is held.
+ {
+ // Snap the head and tail
+ head = _head;
+ tail = _tail;
+ Debug.Assert(head != null);
+ Debug.Assert(tail != null);
+ Debug.Assert(tail._nextSegment == null);
+
+ // Mark them and all segments in between as preserving, and ensure no additional items
+ // can be added to the tail.
+ for (ConcurrentQueueSegment<T> s = head; ; s = s._nextSegment)
+ {
+ s._preservedForObservation = true;
+ if (s == tail) break;
+ Debug.Assert(s._frozenForEnqueues); // any non-tail should already be marked
+ }
+ tail.EnsureFrozenForEnqueues(); // we want to prevent the tailTail from moving
+
+ // At this point, any dequeues from any segment won't overwrite the value, and
+ // none of the existing segments can have new items enqueued.
+
+ headHead = Volatile.Read(ref head._headAndTail.Head);
+ tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ }
+ }
+
+ /// <summary>Gets the item stored in the <paramref name="i"/>th entry in <paramref name="segment"/>.</summary>
+ private T GetItemWhenAvailable(ConcurrentQueueSegment<T> segment, int i)
+ {
+ Debug.Assert(segment._preservedForObservation);
+
+ // Get the expected value for the sequence number
+ int expectedSequenceNumberAndMask = (i + 1) & segment._slotsMask;
+
+ // If the expected sequence number is not yet written, we're still waiting for
+ // an enqueuer to finish storing it. Spin until it's there.
+ if ((segment._slots[i].SequenceNumber & segment._slotsMask) != expectedSequenceNumberAndMask)
+ {
+ var spinner = new SpinWait();
+ while ((Volatile.Read(ref segment._slots[i].SequenceNumber) & segment._slotsMask) != expectedSequenceNumberAndMask)
+ {
+ spinner.SpinOnce();
+ }
+ }
+
+ // Return the value from the slot.
+ return segment._slots[i].Item;
+ }
+
+ private IEnumerator<T> Enumerate(ConcurrentQueueSegment<T> head, int headHead, ConcurrentQueueSegment<T> tail, int tailTail)
+ {
+ Debug.Assert(head._preservedForObservation);
+ Debug.Assert(head._frozenForEnqueues);
+ Debug.Assert(tail._preservedForObservation);
+ Debug.Assert(tail._frozenForEnqueues);
+
+ // Head segment. We've already marked it as not accepting any more enqueues,
+ // so its tail position is fixed, and we've already marked it as preserved for
+ // enumeration (before we grabbed its head), so we can safely enumerate from
+ // its head to its tail.
+ int headTail = (head == tail ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset;
+ if (headHead < headTail)
+ {
+ headHead &= head._slotsMask;
+ headTail &= head._slotsMask;
+
+ if (headHead < headTail)
+ {
+ for (int i = headHead; i < headTail; i++) yield return GetItemWhenAvailable(head, i);
+ }
+ else
+ {
+ for (int i = headHead; i < head._slots.Length; i++) yield return GetItemWhenAvailable(head, i);
+ for (int i = 0; i < headTail; i++) yield return GetItemWhenAvailable(head, i);
+ }
+ }
+
+ // We've enumerated the head. If the tail is the same, we're done.
+ if (head != tail)
+ {
+ // Each segment between head and tail, not including head and tail. Since there were
+ // segments before these, for our purposes we consider it to start at the 0th element.
+ for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
+ {
+ Debug.Assert(s._preservedForObservation, "Would have had to been preserved as a segment part of enumeration");
+ Debug.Assert(s._frozenForEnqueues, "Would have had to be frozen for enqueues as it's intermediate");
+
+ int sTail = s._headAndTail.Tail - s.FreezeOffset;
+ for (int i = 0; i < sTail; i++)
+ {
+ yield return GetItemWhenAvailable(s, i);
+ }
+ }
+
+ // Enumerate the tail. Since there were segments before this, we can just start at
+ // its beginning, and iterate until the tail we already grabbed.
+ tailTail -= tail.FreezeOffset;
+ for (int i = 0; i < tailTail; i++)
+ {
+ yield return GetItemWhenAvailable(tail, i);
+ }
+ }
+ }
+
+ /// <summary>Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.</summary>
+ /// <param name="item">
+ /// The object to add to the end of the <see cref="ConcurrentQueue{T}"/>.
+ /// The value can be a null reference (Nothing in Visual Basic) for reference types.
+ /// </param>
+ public void Enqueue(T item)
+ {
+ // Try to enqueue to the current tail.
+ if (!_tail.TryEnqueue(item))
+ {
+ // If we're unable to, we need to take a slow path that will
+ // try to add a new tail segment.
+ EnqueueSlow(item);
+ }
+ }
+
+ /// <summary>Adds to the end of the queue, adding a new segment if necessary.</summary>
+ private void EnqueueSlow(T item)
+ {
+ while (true)
+ {
+ ConcurrentQueueSegment<T> tail = _tail;
+
+ // Try to append to the existing tail.
+ if (tail.TryEnqueue(item))
+ {
+ return;
+ }
+
+ // If we were unsuccessful, take the lock so that we can compare and manipulate
+ // the tail. Assuming another enqueuer hasn't already added a new segment,
+ // do so, then loop around to try enqueueing again.
+ lock (_crossSegmentLock)
+ {
+ if (tail == _tail)
+ {
+ // Make sure no one else can enqueue to this segment.
+ tail.EnsureFrozenForEnqueues();
+
+ // We determine the new segment's length based on the old length.
+ // In general, we double the size of the segment, to make it less likely
+ // that we'll need to grow again. However, if the tail segment is marked
+ // as preserved for observation, something caused us to avoid reusing this
+ // segment, and if that happens a lot and we grow, we'll end up allocating
+ // lots of wasted space. As such, in such situations we reset back to the
+ // initial segment length; if these observations are happening frequently,
+ // this will help to avoid wasted memory, and if they're not, we'll
+ // relatively quickly grow again to a larger size.
+ int nextSize = tail._preservedForObservation ? InitialSegmentLength : Math.Min(tail.Capacity * 2, MaxSegmentLength);
+ var newTail = new ConcurrentQueueSegment<T>(nextSize);
+
+ // Hook up the new tail.
+ tail._nextSegment = newTail;
+ _tail = newTail;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Attempts to remove and return the object at the beginning of the <see
+ /// cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ /// <param name="result">
+ /// When this method returns, if the operation was successful, <paramref name="result"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>
+ /// true if an element was removed and returned from the beginning of the
+ /// <see cref="ConcurrentQueue{T}"/> successfully; otherwise, false.
+ /// </returns>
+ public bool TryDequeue(out T result) =>
+ _head.TryDequeue(out result) || // fast-path that operates just on the head segment
+ TryDequeueSlow(out result); // slow path that needs to fix up segments
+
+ /// <summary>Tries to dequeue an item, removing empty segments as needed.</summary>
+ private bool TryDequeueSlow(out T item)
+ {
+ while (true)
+ {
+ // Get the current head
+ ConcurrentQueueSegment<T> head = _head;
+
+ // Try to take. If we're successful, we're done.
+ if (head.TryDequeue(out item))
+ {
+ return true;
+ }
+
+ // Check to see whether this segment is the last. If it is, we can consider
+ // this to be a moment-in-time empty condition (even though between the TryDequeue
+ // check and this check, another item could have arrived).
+ if (head._nextSegment == null)
+ {
+ item = default;
+ return false;
+ }
+
+ // At this point we know that head.Next != null, which means
+ // this segment has been frozen for additional enqueues. But between
+ // the time that we ran TryDequeue and checked for a next segment,
+ // another item could have been added. Try to dequeue one more time
+ // to confirm that the segment is indeed empty.
+ Debug.Assert(head._frozenForEnqueues);
+ if (head.TryDequeue(out item))
+ {
+ return true;
+ }
+
+ // This segment is frozen (nothing more can be added) and empty (nothing is in it).
+ // Update head to point to the next segment in the list, assuming no one's beat us to it.
+ lock (_crossSegmentLock)
+ {
+ if (head == _head)
+ {
+ _head = head._nextSegment;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Attempts to return an object from the beginning of the <see cref="ConcurrentQueue{T}"/>
+ /// without removing it.
+ /// </summary>
+ /// <param name="result">
+ /// When this method returns, <paramref name="result"/> contains an object from
+ /// the beginning of the <see cref="Concurrent.ConcurrentQueue{T}"/> or default(T)
+ /// if the operation failed.
+ /// </param>
+ /// <returns>true if and object was returned successfully; otherwise, false.</returns>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
+ /// property is recommended rather than peeking.
+ /// </remarks>
+ public bool TryPeek(out T result) => TryPeek(out result, resultUsed: true);
+
+ /// <summary>Attempts to retrieve the value for the first element in the queue.</summary>
+ /// <param name="result">The value of the first element, if found.</param>
+ /// <param name="resultUsed">true if the result is needed; otherwise false if only the true/false outcome is needed.</param>
+ /// <returns>true if an element was found; otherwise, false.</returns>
+ private bool TryPeek(out T result, bool resultUsed)
+ {
+ // Starting with the head segment, look through all of the segments
+ // for the first one we can find that's not empty.
+ ConcurrentQueueSegment<T> s = _head;
+ while (true)
+ {
+ // Grab the next segment from this one, before we peek.
+ // This is to be able to see whether the value has changed
+ // during the peek operation.
+ ConcurrentQueueSegment<T> next = Volatile.Read(ref s._nextSegment);
+
+ // Peek at the segment. If we find an element, we're done.
+ if (s.TryPeek(out result, resultUsed))
+ {
+ return true;
+ }
+
+ // The current segment was empty at the moment we checked.
+
+ if (next != null)
+ {
+ // If prior to the peek there was already a next segment, then
+ // during the peek no additional items could have been enqueued
+ // to it and we can just move on to check the next segment.
+ Debug.Assert(next == s._nextSegment);
+ s = next;
+ }
+ else if (Volatile.Read(ref s._nextSegment) == null)
+ {
+ // The next segment is null. Nothing more to peek at.
+ break;
+ }
+
+ // The next segment was null before we peeked but non-null after.
+ // That means either when we peeked the first segment had
+ // already been frozen but the new segment not yet added,
+ // or that the first segment was empty and between the time
+ // that we peeked and then checked _nextSegment, so many items
+ // were enqueued that we filled the first segment and went
+ // into the next. Since we need to peek in order, we simply
+ // loop around again to peek on the same segment. The next
+ // time around on this segment we'll then either successfully
+ // peek or we'll find that next was non-null before peeking,
+ // and we'll traverse to that segment.
+ }
+
+ result = default;
+ return false;
+ }
+
+ /// <summary>
+ /// Removes all objects from the <see cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ public void Clear()
+ {
+ lock (_crossSegmentLock)
+ {
+ // Simply substitute a new segment for the existing head/tail,
+ // as is done in the constructor. Operations currently in flight
+ // may still read from or write to an existing segment that's
+ // getting dropped, meaning that in flight operations may not be
+ // linear with regards to this clear operation. To help mitigate
+ // in-flight operations enqueuing onto the tail that's about to
+ // be dropped, we first freeze it; that'll force enqueuers to take
+ // this lock to synchronize and see the new tail.
+ _tail.EnsureFrozenForEnqueues();
+ _tail = _head = new ConcurrentQueueSegment<T>(InitialSegmentLength);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs
new file mode 100644
index 000000000..12e92d0e0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs
@@ -0,0 +1,332 @@
+// 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.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// Provides a multi-producer, multi-consumer thread-safe bounded segment. When the queue is full,
+ /// enqueues fail and return false. When the queue is empty, dequeues fail and return null.
+ /// These segments are linked together to form the unbounded <see cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ [DebuggerDisplay("Capacity = {Capacity}")]
+ internal sealed class ConcurrentQueueSegment<T>
+ {
+ // Segment design is inspired by the algorithm outlined at:
+ // http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
+
+ /// <summary>The array of items in this queue. Each slot contains the item in that slot and its "sequence number".</summary>
+ internal readonly Slot[] _slots;
+ /// <summary>Mask for quickly accessing a position within the queue's array.</summary>
+ internal readonly int _slotsMask;
+ /// <summary>The head and tail positions, with padding to help avoid false sharing contention.</summary>
+ /// <remarks>Dequeuing happens from the head, enqueuing happens at the tail.</remarks>
+ internal PaddedHeadAndTail _headAndTail; // mutable struct: do not make this readonly
+
+ /// <summary>Indicates whether the segment has been marked such that dequeues don't overwrite the removed data.</summary>
+ internal bool _preservedForObservation;
+ /// <summary>Indicates whether the segment has been marked such that no additional items may be enqueued.</summary>
+ internal bool _frozenForEnqueues;
+#pragma warning disable 0649 // some builds don't assign to this field
+ /// <summary>The segment following this one in the queue, or null if this segment is the last in the queue.</summary>
+ internal ConcurrentQueueSegment<T> _nextSegment;
+#pragma warning restore 0649
+
+ /// <summary>Creates the segment.</summary>
+ /// <param name="boundedLength">
+ /// The maximum number of elements the segment can contain. Must be a power of 2.
+ /// </param>
+ internal ConcurrentQueueSegment(int boundedLength)
+ {
+ // Validate the length
+ Debug.Assert(boundedLength >= 2, $"Must be >= 2, got {boundedLength}");
+ Debug.Assert((boundedLength & (boundedLength - 1)) == 0, $"Must be a power of 2, got {boundedLength}");
+
+ // Initialize the slots and the mask. The mask is used as a way of quickly doing "% _slots.Length",
+ // instead letting us do "& _slotsMask".
+ _slots = new Slot[boundedLength];
+ _slotsMask = boundedLength - 1;
+
+ // Initialize the sequence number for each slot. The sequence number provides a ticket that
+ // allows dequeuers to know whether they can dequeue and enqueuers to know whether they can
+ // enqueue. An enqueuer at position N can enqueue when the sequence number is N, and a dequeuer
+ // for position N can dequeue when the sequence number is N + 1. When an enqueuer is done writing
+ // at position N, it sets the sequence number to N + 1 so that a dequeuer will be able to dequeue,
+ // and when a dequeuer is done dequeueing at position N, it sets the sequence number to N + _slots.Length,
+ // so that when an enqueuer loops around the slots, it'll find that the sequence number at
+ // position N is N. This also means that when an enqueuer finds that at position N the sequence
+ // number is < N, there is still a value in that slot, i.e. the segment is full, and when a
+ // dequeuer finds that the value in a slot is < N + 1, there is nothing currently available to
+ // dequeue. (It is possible for multiple enqueuers to enqueue concurrently, writing into
+ // subsequent slots, and to have the first enqueuer take longer, so that the slots for 1, 2, 3, etc.
+ // may have values, but the 0th slot may still be being filled... in that case, TryDequeue will
+ // return false.)
+ for (int i = 0; i < _slots.Length; i++)
+ {
+ _slots[i].SequenceNumber = i;
+ }
+ }
+
+ /// <summary>Round the specified value up to the next power of 2, if it isn't one already.</summary>
+ internal static int RoundUpToPowerOf2(int i)
+ {
+ // Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ --i;
+ i |= i >> 1;
+ i |= i >> 2;
+ i |= i >> 4;
+ i |= i >> 8;
+ i |= i >> 16;
+ return i + 1;
+ }
+
+ /// <summary>Gets the number of elements this segment can store.</summary>
+ internal int Capacity => _slots.Length;
+
+ /// <summary>Gets the "freeze offset" for this segment.</summary>
+ internal int FreezeOffset => _slots.Length * 2;
+
+ /// <summary>
+ /// Ensures that the segment will not accept any subsequent enqueues that aren't already underway.
+ /// </summary>
+ /// <remarks>
+ /// When we mark a segment as being frozen for additional enqueues,
+ /// we set the <see cref="_frozenForEnqueues"/> bool, but that's mostly
+ /// as a small helper to avoid marking it twice. The real marking comes
+ /// by modifying the Tail for the segment, increasing it by this
+ /// <see cref="FreezeOffset"/>. This effectively knocks it off the
+ /// sequence expected by future enqueuers, such that any additional enqueuer
+ /// will be unable to enqueue due to it not lining up with the expected
+ /// sequence numbers. This value is chosen specially so that Tail will grow
+ /// to a value that maps to the same slot but that won't be confused with
+ /// any other enqueue/dequeue sequence number.
+ /// </remarks>
+ internal void EnsureFrozenForEnqueues() // must only be called while queue's segment lock is held
+ {
+ if (!_frozenForEnqueues) // flag used to ensure we don't increase the Tail more than once if frozen more than once
+ {
+ _frozenForEnqueues = true;
+
+ // Increase the tail by FreezeOffset, spinning until we're successful in doing so.
+ var spinner = new SpinWait();
+ while (true)
+ {
+ int tail = Volatile.Read(ref _headAndTail.Tail);
+ if (Interlocked.CompareExchange(ref _headAndTail.Tail, tail + FreezeOffset, tail) == tail)
+ {
+ break;
+ }
+ spinner.SpinOnce();
+ }
+ }
+ }
+
+ /// <summary>Tries to dequeue an element from the queue.</summary>
+ public bool TryDequeue(out T item)
+ {
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Get the head at which to try to dequeue.
+ int currentHead = Volatile.Read(ref _headAndTail.Head);
+ int slotsIndex = currentHead & _slotsMask;
+
+ // Read the sequence number for the head position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // We can dequeue from this slot if it's been filled by an enqueuer, which
+ // would have left the sequence number at pos+1.
+ int diff = sequenceNumber - (currentHead + 1);
+ if (diff == 0)
+ {
+ // We may be racing with other dequeuers. Try to reserve the slot by incrementing
+ // the head. Once we've done that, no one else will be able to read from this slot,
+ // and no enqueuer will be able to read from this slot until we've written the new
+ // sequence number. WARNING: The next few lines are not reliable on a runtime that
+ // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
+ // but before the Volatile.Write, enqueuers trying to enqueue into this slot would
+ // spin indefinitely. If this implementation is ever used on such a platform, this
+ // if block should be wrapped in a finally / prepared region.
+ if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead)
+ {
+ // Successfully reserved the slot. Note that after the above CompareExchange, other threads
+ // trying to dequeue from this slot will end up spinning until we do the subsequent Write.
+ item = _slots[slotsIndex].Item;
+ if (!Volatile.Read(ref _preservedForObservation))
+ {
+ // If we're preserving, though, we don't zero out the slot, as we need it for
+ // enumerations, peeking, ToArray, etc. And we don't update the sequence number,
+ // so that an enqueuer will see it as full and be forced to move to a new segment.
+ _slots[slotsIndex].Item = default(T);
+ Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentHead + _slots.Length);
+ }
+ return true;
+ }
+ }
+ else if (diff < 0)
+ {
+ // The sequence number was less than what we needed, which means this slot doesn't
+ // yet contain a value we can dequeue, i.e. the segment is empty. Technically it's
+ // possible that multiple enqueuers could have written concurrently, with those
+ // getting later slots actually finishing first, so there could be elements after
+ // this one that are available, but we need to dequeue in order. So before declaring
+ // failure and that the segment is empty, we check the tail to see if we're actually
+ // empty or if we're just waiting for items in flight or after this one to become available.
+ bool frozen = _frozenForEnqueues;
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
+ {
+ item = default(T);
+ return false;
+ }
+
+ // It's possible it could have become frozen after we checked _frozenForEnqueues
+ // and before reading the tail. That's ok: in that rare race condition, we just
+ // loop around again.
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>Tries to peek at an element from the queue, without removing it.</summary>
+ public bool TryPeek(out T result, bool resultUsed)
+ {
+ if (resultUsed)
+ {
+ // In order to ensure we don't get a torn read on the value, we mark the segment
+ // as preserving for observation. Additional items can still be enqueued to this
+ // segment, but no space will be freed during dequeues, such that the segment will
+ // no longer be reusable.
+ _preservedForObservation = true;
+ Interlocked.MemoryBarrier();
+ }
+
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Get the head at which to try to peek.
+ int currentHead = Volatile.Read(ref _headAndTail.Head);
+ int slotsIndex = currentHead & _slotsMask;
+
+ // Read the sequence number for the head position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // We can peek from this slot if it's been filled by an enqueuer, which
+ // would have left the sequence number at pos+1.
+ int diff = sequenceNumber - (currentHead + 1);
+ if (diff == 0)
+ {
+ result = resultUsed ? _slots[slotsIndex].Item : default(T);
+ return true;
+ }
+ else if (diff < 0)
+ {
+ // The sequence number was less than what we needed, which means this slot doesn't
+ // yet contain a value we can peek, i.e. the segment is empty. Technically it's
+ // possible that multiple enqueuers could have written concurrently, with those
+ // getting later slots actually finishing first, so there could be elements after
+ // this one that are available, but we need to peek in order. So before declaring
+ // failure and that the segment is empty, we check the tail to see if we're actually
+ // empty or if we're just waiting for items in flight or after this one to become available.
+ bool frozen = _frozenForEnqueues;
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
+ {
+ result = default(T);
+ return false;
+ }
+
+ // It's possible it could have become frozen after we checked _frozenForEnqueues
+ // and before reading the tail. That's ok: in that rare race condition, we just
+ // loop around again.
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>
+ /// Attempts to enqueue the item. If successful, the item will be stored
+ /// in the queue and true will be returned; otherwise, the item won't be stored, and false
+ /// will be returned.
+ /// </summary>
+ public bool TryEnqueue(T item)
+ {
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Get the tail at which to try to return.
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ int slotsIndex = currentTail & _slotsMask;
+
+ // Read the sequence number for the tail position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // The slot is empty and ready for us to enqueue into it if its sequence
+ // number matches the slot.
+ int diff = sequenceNumber - currentTail;
+ if (diff == 0)
+ {
+ // We may be racing with other enqueuers. Try to reserve the slot by incrementing
+ // the tail. Once we've done that, no one else will be able to write to this slot,
+ // and no dequeuer will be able to read from this slot until we've written the new
+ // sequence number. WARNING: The next few lines are not reliable on a runtime that
+ // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
+ // but before the Volatile.Write, other threads will spin trying to access this slot.
+ // If this implementation is ever used on such a platform, this if block should be
+ // wrapped in a finally / prepared region.
+ if (Interlocked.CompareExchange(ref _headAndTail.Tail, currentTail + 1, currentTail) == currentTail)
+ {
+ // Successfully reserved the slot. Note that after the above CompareExchange, other threads
+ // trying to return will end up spinning until we do the subsequent Write.
+ _slots[slotsIndex].Item = item;
+ Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentTail + 1);
+ return true;
+ }
+ }
+ else if (diff < 0)
+ {
+ // The sequence number was less than what we needed, which means this slot still
+ // contains a value, i.e. the segment is full. Technically it's possible that multiple
+ // dequeuers could have read concurrently, with those getting later slots actually
+ // finishing first, so there could be spaces after this one that are available, but
+ // we need to enqueue in order.
+ return false;
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>Represents a slot in the queue.</summary>
+ [StructLayout(LayoutKind.Auto)]
+ [DebuggerDisplay("Item = {Item}, SequenceNumber = {SequenceNumber}")]
+ internal struct Slot
+ {
+ /// <summary>The item.</summary>
+ public T Item;
+ /// <summary>The sequence number for this slot, used to synchronize between enqueuers and dequeuers.</summary>
+ public int SequenceNumber;
+ }
+ }
+
+ /// <summary>Padded head and tail indices, to avoid false sharing between producers and consumers.</summary>
+ [DebuggerDisplay("Head = {Head}, Tail = {Tail}")]
+ [StructLayout(LayoutKind.Explicit, Size = 3 * Internal.PaddingHelpers.CACHE_LINE_SIZE)] // padding before/between/after fields
+ internal struct PaddedHeadAndTail
+ {
+ [FieldOffset(1 * Internal.PaddingHelpers.CACHE_LINE_SIZE)] public int Head;
+ [FieldOffset(2 * Internal.PaddingHelpers.CACHE_LINE_SIZE)] public int Tail;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs
new file mode 100644
index 000000000..972715056
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs
@@ -0,0 +1,70 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// A common interface for all concurrent collections.
+ /// Defines methods to manipulate thread-safe collections intended for producer/consumer usage.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the collection.</typeparam>
+ /// <remarks>
+ /// All implementations of this interface must enable all members of this interface
+ /// to be used concurrently from multiple threads.
+ /// </remarks>
+ public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection
+ {
+ /// <summary>
+ /// Copies the elements of the <see cref="IProducerConsumerCollection{T}"/> to
+ /// an
+ /// <see cref="T:System.Array"/>, starting at a specified index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of
+ /// the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.
+ /// The array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
+ /// length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
+ /// available space from <paramref name="index"/> to the end of the destination <paramref
+ /// name="array"/>.
+ /// </exception>
+ void CopyTo(T[] array, int index);
+
+ /// <summary>
+ /// Attempts to add an object to the <see
+ /// cref="IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="IProducerConsumerCollection{T}"/>.</param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentException">The <paramref name="item"/> was invalid for this collection.</exception>
+ bool TryAdd(T item);
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see cref="IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the object was removed and returned successfully, <paramref
+ /// name="item"/> contains the removed object. If no object was available to be removed, the value is
+ /// unspecified.
+ /// </param>
+ /// <returns>true if an object was removed and returned successfully; otherwise, false.</returns>
+ bool TryTake(out T item);
+
+ /// <summary>
+ /// Copies the elements contained in the <see cref="IProducerConsumerCollection{T}"/> to a new array.
+ /// </summary>
+ /// <returns>A new array containing the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.</returns>
+ T[] ToArray();
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs
new file mode 100644
index 000000000..0205e068e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs
@@ -0,0 +1,41 @@
+// 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.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// A debugger view of the IProducerConsumerCollection that makes it simple to browse the
+ /// collection's contents at a point in time.
+ /// </summary>
+ /// <typeparam name="T">The type of elements stored within.</typeparam>
+ internal sealed class IProducerConsumerCollectionDebugView<T>
+ {
+ private readonly IProducerConsumerCollection<T> _collection; // The collection being viewed.
+
+ /// <summary>
+ /// Constructs a new debugger view object for the provided collection object.
+ /// </summary>
+ /// <param name="collection">A collection to browse in the debugger.</param>
+ public IProducerConsumerCollectionDebugView(IProducerConsumerCollection<T> collection)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ _collection = collection;
+ }
+
+ /// <summary>
+ /// Returns a snapshot of the underlying collection's elements.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Items
+ {
+ get { return _collection.ToArray(); }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs b/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
index d0cbcb666..eabb01376 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
@@ -16,18 +16,18 @@ namespace System.Collections
#endif
public struct DictionaryEntry
{
- private Object _key; // Do not rename (binary serialization)
- private Object _value; // Do not rename (binary serialization)
+ private object _key; // Do not rename (binary serialization)
+ private object _value; // Do not rename (binary serialization)
// Constructs a new DictionaryEnumerator by setting the Key
// and Value fields appropriately.
- public DictionaryEntry(Object key, Object value)
+ public DictionaryEntry(object key, object value)
{
_key = key;
_value = value;
}
- public Object Key
+ public object Key
{
get
{
@@ -40,7 +40,7 @@ namespace System.Collections
}
}
- public Object Value
+ public object Value
{
get
{
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs
new file mode 100644
index 000000000..03b986504
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs
@@ -0,0 +1,1115 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: class to sort arrays
+**
+**
+===========================================================*/
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Collections.Generic
+{
+ #region ArraySortHelper for single arrays
+
+ internal static class IntrospectiveSortUtilities
+ {
+ // This is the threshold where Introspective sort switches to Insertion sort.
+ // Empirically, 16 seems to speed up most cases without slowing down others, at least for integers.
+ // Large value types may benefit from a smaller number.
+ internal const int IntrosortSizeThreshold = 16;
+
+ internal static int FloorLog2PlusOne(int n)
+ {
+ int result = 0;
+ while (n >= 1)
+ {
+ result++;
+ n = n / 2;
+ }
+ return result;
+ }
+
+ internal static void ThrowOrIgnoreBadComparer(object comparer)
+ {
+ throw new ArgumentException(SR.Format(SR.Arg_BogusIComparer, comparer));
+ }
+ }
+
+ internal partial class ArraySortHelper<T>
+ {
+ #region IArraySortHelper<T> Members
+
+ public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null)
+ {
+ comparer = Comparer<T>.Default;
+ }
+
+ IntrospectiveSort(keys, index, length, comparer.Compare);
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ try
+ {
+ if (comparer == null)
+ {
+ comparer = Comparer<T>.Default;
+ }
+
+ return InternalBinarySearch(array, index, length, value, comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ #endregion
+
+ internal static void Sort(T[] keys, int index, int length, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+ Debug.Assert(comparer != null, "Check the arguments in the caller!");
+
+ // Add a try block here to detect bogus comparisons
+ try
+ {
+ IntrospectiveSort(keys, index, length, comparer);
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ internal static int InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ Debug.Assert(array != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
+
+ int lo = index;
+ int hi = index + length - 1;
+ while (lo <= hi)
+ {
+ int i = lo + ((hi - lo) >> 1);
+ int order = comparer.Compare(array[i], value);
+
+ if (order == 0) return i;
+ if (order < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i - 1;
+ }
+ }
+
+ return ~lo;
+ }
+
+ private static void SwapIfGreater(T[] keys, Comparison<T> comparer, int a, int b)
+ {
+ if (a != b)
+ {
+ if (comparer(keys[a], keys[b]) > 0)
+ {
+ T key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ }
+ }
+ }
+
+ private static void Swap(T[] a, int i, int j)
+ {
+ if (i != j)
+ {
+ T t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+ }
+
+ internal static void IntrospectiveSort(T[] keys, int left, int length, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length), comparer);
+ }
+
+ private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreater(keys, comparer, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreater(keys, comparer, lo, hi - 1);
+ SwapIfGreater(keys, comparer, lo, hi);
+ SwapIfGreater(keys, comparer, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, lo, hi, comparer);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, lo, hi, comparer);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, lo, hi, comparer);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, p + 1, hi, depthLimit, comparer);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(T[] keys, int lo, int hi, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreater(keys, comparer, lo, middle); // swap the low with the mid point
+ SwapIfGreater(keys, comparer, lo, hi); // swap the low with the high
+ SwapIfGreater(keys, comparer, middle, hi); // swap the middle with the high
+
+ T pivot = keys[middle];
+ Swap(keys, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer(keys[++left], pivot) < 0) ;
+ while (comparer(pivot, keys[--right]) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(keys, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(T[] keys, int lo, int hi, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, i, n, lo, comparer);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, lo, lo + i - 1);
+ DownHeap(keys, 1, i - 1, lo, comparer);
+ }
+ }
+
+ private static void DownHeap(T[] keys, int i, int n, int lo, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ T d = keys[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ }
+
+ private static void InsertionSort(T[] keys, int lo, int hi, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ T t;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ while (j >= lo && comparer(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ }
+ }
+ }
+
+ internal partial class GenericArraySortHelper<T>
+ where T : IComparable<T>
+ {
+ // Do not add a constructor to this class because ArraySortHelper<T>.CreateSortHelper will not execute it
+
+ #region IArraySortHelper<T> Members
+
+ public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ try
+ {
+ if (comparer == null || comparer == Comparer<T>.Default)
+ {
+ IntrospectiveSort(keys, index, length);
+ }
+ else
+ {
+ ArraySortHelper<T>.IntrospectiveSort(keys, index, length, comparer.Compare);
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ Debug.Assert(array != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
+
+ try
+ {
+ if (comparer == null || comparer == Comparer<T>.Default)
+ {
+ return BinarySearch(array, index, length, value);
+ }
+ else
+ {
+ return ArraySortHelper<T>.InternalBinarySearch(array, index, length, value, comparer);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ #endregion
+
+ // This function is called when the user doesn't specify any comparer.
+ // Since T is constrained here, we can call IComparable<T>.CompareTo here.
+ // We can avoid boxing for value type and casting for reference types.
+ private static int BinarySearch(T[] array, int index, int length, T value)
+ {
+ int lo = index;
+ int hi = index + length - 1;
+ while (lo <= hi)
+ {
+ int i = lo + ((hi - lo) >> 1);
+ int order;
+ if (array[i] == null)
+ {
+ order = (value == null) ? 0 : -1;
+ }
+ else
+ {
+ order = array[i].CompareTo(value);
+ }
+
+ if (order == 0)
+ {
+ return i;
+ }
+
+ if (order < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i - 1;
+ }
+ }
+
+ return ~lo;
+ }
+
+ private static void SwapIfGreaterWithItems(T[] keys, int a, int b)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(0 <= a && a < keys.Length);
+ Debug.Assert(0 <= b && b < keys.Length);
+
+ if (a != b)
+ {
+ if (keys[a] != null && keys[a].CompareTo(keys[b]) > 0)
+ {
+ T key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ }
+ }
+ }
+
+ private static void Swap(T[] a, int i, int j)
+ {
+ if (i != j)
+ {
+ T t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+ }
+
+ internal static void IntrospectiveSort(T[] keys, int left, int length)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length));
+ }
+
+ private static void IntroSort(T[] keys, int lo, int hi, int depthLimit)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, lo, hi - 1);
+ SwapIfGreaterWithItems(keys, lo, hi);
+ SwapIfGreaterWithItems(keys, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, lo, hi);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(T[] keys, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, middle, hi); // swap the middle with the high
+
+ T pivot = keys[middle];
+ Swap(keys, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ if (pivot == null)
+ {
+ while (left < (hi - 1) && keys[++left] == null) ;
+ while (right > lo && keys[--right] != null) ;
+ }
+ else
+ {
+ while (pivot.CompareTo(keys[++left]) > 0) ;
+ while (pivot.CompareTo(keys[--right]) < 0) ;
+ }
+
+ if (left >= right)
+ break;
+
+ Swap(keys, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(T[] keys, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, lo, lo + i - 1);
+ DownHeap(keys, 1, i - 1, lo);
+ }
+ }
+
+ private static void DownHeap(T[] keys, int i, int n, int lo)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ T d = keys[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(keys[lo + child]) < 0))
+ {
+ child++;
+ }
+ if (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(d) < 0)
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ }
+
+ private static void InsertionSort(T[] keys, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ T t;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ while (j >= lo && (t == null || t.CompareTo(keys[j]) < 0))
+ {
+ keys[j + 1] = keys[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ }
+ }
+ }
+
+ #endregion
+
+ #region ArraySortHelper for paired key and value arrays
+
+ internal partial class ArraySortHelper<TKey, TValue>
+ {
+ public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method
+ Debug.Assert(values != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null || comparer == Comparer<TKey>.Default)
+ {
+ comparer = Comparer<TKey>.Default;
+ }
+
+ IntrospectiveSort(keys, values, index, length, comparer);
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, IComparer<TKey> comparer, int a, int b)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(0 <= a && a < keys.Length && a < values.Length);
+ Debug.Assert(0 <= b && b < keys.Length && b < values.Length);
+
+ if (a != b)
+ {
+ if (comparer.Compare(keys[a], keys[b]) > 0)
+ {
+ TKey key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+
+ TValue value = values[a];
+ values[a] = values[b];
+ values[b] = value;
+ }
+ }
+ }
+
+ private static void Swap(TKey[] keys, TValue[] values, int i, int j)
+ {
+ if (i != j)
+ {
+ TKey k = keys[i];
+ keys[i] = keys[j];
+ keys[j] = k;
+
+ TValue v = values[i];
+ values[i] = values[j];
+ values[j] = v;
+ }
+ }
+
+ internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+ Debug.Assert(length + left <= values.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length), comparer);
+ }
+
+ private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi - 1);
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
+ SwapIfGreaterWithItems(keys, values, comparer, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, values, lo, hi, comparer);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, lo, hi, comparer);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, values, lo, hi, comparer);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, values, p + 1, hi, depthLimit, comparer);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, values, comparer, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, comparer, middle, hi); // swap the middle with the high
+
+ TKey pivot = keys[middle];
+ Swap(keys, values, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer.Compare(keys[++left], pivot) < 0) ;
+ while (comparer.Compare(pivot, keys[--right]) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(keys, values, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, values, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, values, i, n, lo, comparer);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, values, lo, lo + i - 1);
+ DownHeap(keys, values, 1, i - 1, lo, comparer);
+ }
+ }
+
+ private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ TKey d = keys[lo + i - 1];
+ TValue dValue = values[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ values[lo + i - 1] = values[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ values[lo + i - 1] = dValue;
+ }
+
+ private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ TKey t;
+ TValue tValue;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ tValue = values[i + 1];
+ while (j >= lo && comparer.Compare(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ values[j + 1] = values[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ values[j + 1] = tValue;
+ }
+ }
+ }
+
+ internal partial class GenericArraySortHelper<TKey, TValue>
+ where TKey : IComparable<TKey>
+ {
+ public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null || comparer == Comparer<TKey>.Default)
+ {
+ IntrospectiveSort(keys, values, index, length);
+ }
+ else
+ {
+ ArraySortHelper<TKey, TValue>.IntrospectiveSort(keys, values, index, length, comparer);
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, int a, int b)
+ {
+ if (a != b)
+ {
+ if (keys[a] != null && keys[a].CompareTo(keys[b]) > 0)
+ {
+ TKey key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+
+ TValue value = values[a];
+ values[a] = values[b];
+ values[b] = value;
+ }
+ }
+ }
+
+ private static void Swap(TKey[] keys, TValue[] values, int i, int j)
+ {
+ if (i != j)
+ {
+ TKey k = keys[i];
+ keys[i] = keys[j];
+ keys[j] = k;
+
+ TValue v = values[i];
+ values[i] = values[j];
+ values[j] = v;
+ }
+ }
+
+ internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+ Debug.Assert(length + left <= values.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length));
+ }
+
+ private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, values, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, values, lo, hi - 1);
+ SwapIfGreaterWithItems(keys, values, lo, hi);
+ SwapIfGreaterWithItems(keys, values, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, values, lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, values, lo, hi);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, values, p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, values, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, middle, hi); // swap the middle with the high
+
+ TKey pivot = keys[middle];
+ Swap(keys, values, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ if (pivot == null)
+ {
+ while (left < (hi - 1) && keys[++left] == null) ;
+ while (right > lo && keys[--right] != null) ;
+ }
+ else
+ {
+ while (pivot.CompareTo(keys[++left]) > 0) ;
+ while (pivot.CompareTo(keys[--right]) < 0) ;
+ }
+
+ if (left >= right)
+ break;
+
+ Swap(keys, values, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, values, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, values, i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, values, lo, lo + i - 1);
+ DownHeap(keys, values, 1, i - 1, lo);
+ }
+ }
+
+ private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ TKey d = keys[lo + i - 1];
+ TValue dValue = values[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(keys[lo + child]) < 0))
+ {
+ child++;
+ }
+ if (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(d) < 0)
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ values[lo + i - 1] = values[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ values[lo + i - 1] = dValue;
+ }
+
+ private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ TKey t;
+ TValue tValue;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ tValue = values[i + 1];
+ while (j >= lo && (t == null || t.CompareTo(keys[j]) < 0))
+ {
+ keys[j + 1] = keys[j];
+ values[j + 1] = values[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ values[j + 1] = tValue;
+ }
+ }
+ }
+
+ #endregion
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs
index 76fe546fb..623257d3c 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs
@@ -2,11 +2,10 @@
// 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.Collections;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
+using System.Threading;
namespace System.Collections.Generic
{
@@ -35,7 +34,7 @@ namespace System.Collections.Generic
[DebuggerDisplay("Count = {Count}")]
[Serializable]
#if !MONO
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback
{
@@ -221,7 +220,7 @@ namespace System.Collections.Generic
int i = FindEntry(key);
if (i >= 0) return _entries[i].value;
ThrowHelper.ThrowKeyNotFoundException(key);
- return default(TValue);
+ return default;
}
set
{
@@ -237,9 +236,7 @@ namespace System.Collections.Generic
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
- {
- Add(keyValuePair.Key, keyValuePair.Value);
- }
+ => Add(keyValuePair.Key, keyValuePair.Value);
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
{
@@ -272,30 +269,43 @@ namespace System.Collections.Generic
_count = 0;
_freeList = -1;
_freeCount = 0;
- _version++;
Array.Clear(_entries, 0, count);
}
}
public bool ContainsKey(TKey key)
- {
- return FindEntry(key) >= 0;
- }
+ => FindEntry(key) >= 0;
public bool ContainsValue(TValue value)
{
+ Entry[] entries = _entries;
if (value == null)
{
for (int i = 0; i < _count; i++)
{
- if (_entries[i].hashCode >= 0 && _entries[i].value == null) return true;
+ if (entries[i].hashCode >= 0 && entries[i].value == null) return true;
}
}
else
{
- for (int i = 0; i < _count; i++)
+ if (default(TValue) != null)
+ {
+ // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
+ for (int i = 0; i < _count; i++)
+ {
+ if (entries[i].hashCode >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, value)) return true;
+ }
+ }
+ else
{
- if (_entries[i].hashCode >= 0 && EqualityComparer<TValue>.Default.Equals(_entries[i].value, value)) return true;
+ // Object type: Shared Generic, EqualityComparer<TValue>.Default won't devirtualize
+ // https://github.com/dotnet/coreclr/issues/17273
+ // So cache in a local rather than get EqualityComparer per loop iteration
+ EqualityComparer<TValue> defaultComparer = EqualityComparer<TValue>.Default;
+ for (int i = 0; i < _count; i++)
+ {
+ if (entries[i].hashCode >= 0 && defaultComparer.Equals(entries[i].value, value)) return true;
+ }
}
}
return false;
@@ -308,7 +318,7 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
- if (index < 0 || index > array.Length)
+ if ((uint)index > (uint)array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
@@ -330,14 +340,10 @@ namespace System.Collections.Generic
}
public Enumerator GetEnumerator()
- {
- return new Enumerator(this, Enumerator.KeyValuePair);
- }
+ => new Enumerator(this, Enumerator.KeyValuePair);
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
- {
- return new Enumerator(this, Enumerator.KeyValuePair);
- }
+ => new Enumerator(this, Enumerator.KeyValuePair);
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
@@ -368,6 +374,7 @@ namespace System.Collections.Generic
int i = -1;
int[] buckets = _buckets;
Entry[] entries = _entries;
+ int collisionCount = 0;
if (buckets != null)
{
IEqualityComparer<TKey> comparer = _comparer;
@@ -376,17 +383,53 @@ namespace System.Collections.Generic
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
// Value in _buckets is 1-based
i = buckets[hashCode % buckets.Length] - 1;
- do
+ if (default(TKey) != null)
{
- // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
- // Test in if to drop range check for following array access
- if ((uint)i >= (uint)entries.Length || (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key)))
+ // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
+ do
{
- break;
- }
-
- i = entries[i].next;
- } while (true);
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test in if to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length || (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key)))
+ {
+ break;
+ }
+
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
+ else
+ {
+ // Object type: Shared Generic, EqualityComparer<TValue>.Default won't devirtualize
+ // https://github.com/dotnet/coreclr/issues/17273
+ // So cache in a local rather than get EqualityComparer per loop iteration
+ EqualityComparer<TKey> defaultComparer = EqualityComparer<TKey>.Default;
+ do
+ {
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test in if to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length || (entries[i].hashCode == hashCode && defaultComparer.Equals(entries[i].key, key)))
+ {
+ break;
+ }
+
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
}
else
{
@@ -404,6 +447,13 @@ namespace System.Collections.Generic
}
i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
} while (true);
}
}
@@ -446,35 +496,87 @@ namespace System.Collections.Generic
if (comparer == null)
{
- do
+ if (default(TKey) != null)
{
- // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
- // Test uint in if rather than loop condition to drop range check for following array access
- if ((uint)i >= (uint)entries.Length)
+ // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
+ do
{
- break;
- }
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test uint in if rather than loop condition to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length)
+ {
+ break;
+ }
- if (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key))
- {
- if (behavior == InsertionBehavior.OverwriteExisting)
+ if (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key))
{
- entries[i].value = value;
- _version++;
- return true;
+ if (behavior == InsertionBehavior.OverwriteExisting)
+ {
+ entries[i].value = value;
+ _version++;
+ return true;
+ }
+
+ if (behavior == InsertionBehavior.ThrowOnExisting)
+ {
+ ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+ }
+
+ return false;
}
- if (behavior == InsertionBehavior.ThrowOnExisting)
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
{
- ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
+ else
+ {
+ // Object type: Shared Generic, EqualityComparer<TValue>.Default won't devirtualize
+ // https://github.com/dotnet/coreclr/issues/17273
+ // So cache in a local rather than get EqualityComparer per loop iteration
+ EqualityComparer<TKey> defaultComparer = EqualityComparer<TKey>.Default;
+ do
+ {
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test uint in if rather than loop condition to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length)
+ {
+ break;
}
- return false;
- }
+ if (entries[i].hashCode == hashCode && defaultComparer.Equals(entries[i].key, key))
+ {
+ if (behavior == InsertionBehavior.OverwriteExisting)
+ {
+ entries[i].value = value;
+ _version++;
+ return true;
+ }
+
+ if (behavior == InsertionBehavior.ThrowOnExisting)
+ {
+ ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+ }
+
+ return false;
+ }
- i = entries[i].next;
- collisionCount++;
- } while (true);
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
}
else
{
@@ -505,14 +607,17 @@ namespace System.Collections.Generic
}
i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
collisionCount++;
} while (true);
}
- // Can be improved with "Ref Local Reassignment"
- // https://github.com/dotnet/csharplang/blob/master/proposals/ref-local-reassignment.md
- bool resized = false;
bool updateFreeList = false;
int index;
if (_freeCount > 0)
@@ -527,14 +632,13 @@ namespace System.Collections.Generic
if (count == entries.Length)
{
Resize();
- resized = true;
+ bucket = ref _buckets[hashCode % _buckets.Length];
}
index = count;
_count = count + 1;
entries = _entries;
}
- ref int targetBucket = ref resized ? ref _buckets[hashCode % _buckets.Length] : ref bucket;
ref Entry entry = ref entries[index];
if (updateFreeList)
@@ -543,11 +647,11 @@ namespace System.Collections.Generic
}
entry.hashCode = hashCode;
// Value in _buckets is 1-based
- entry.next = targetBucket - 1;
+ entry.next = bucket - 1;
entry.key = key;
entry.value = value;
// Value in _buckets is 1-based
- targetBucket = index + 1;
+ bucket = index + 1;
_version++;
#if !MONO
@@ -566,8 +670,7 @@ namespace System.Collections.Generic
public virtual void OnDeserialization(object sender)
{
- SerializationInfo siInfo;
- HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
+ HashHelpers.SerializationInfoTable.TryGetValue(this, out SerializationInfo siInfo);
if (siInfo == null)
{
@@ -611,9 +714,7 @@ namespace System.Collections.Generic
}
private void Resize()
- {
- Resize(HashHelpers.ExpandPrime(_count), false);
- }
+ => Resize(HashHelpers.ExpandPrime(_count), false);
private void Resize(int newSize, bool forceNewHashCodes)
{
@@ -665,47 +766,56 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
- if (_buckets != null)
+ int[] buckets = _buckets;
+ Entry[] entries = _entries;
+ int collisionCount = 0;
+ if (buckets != null)
{
int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF;
- int bucket = hashCode % _buckets.Length;
+ int bucket = hashCode % buckets.Length;
int last = -1;
- // Value in _buckets is 1-based
- int i = _buckets[bucket] - 1;
+ // Value in buckets is 1-based
+ int i = buckets[bucket] - 1;
while (i >= 0)
{
- ref Entry entry = ref _entries[i];
+ ref Entry entry = ref entries[i];
if (entry.hashCode == hashCode && (_comparer?.Equals(entry.key, key) ?? EqualityComparer<TKey>.Default.Equals(entry.key, key)))
{
if (last < 0)
{
- // Value in _buckets is 1-based
- _buckets[bucket] = entry.next + 1;
+ // Value in buckets is 1-based
+ buckets[bucket] = entry.next + 1;
}
else
{
- _entries[last].next = entry.next;
+ entries[last].next = entry.next;
}
entry.hashCode = -1;
entry.next = _freeList;
if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>())
{
- entry.key = default(TKey);
+ entry.key = default;
}
if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>())
{
- entry.value = default(TValue);
+ entry.value = default;
}
_freeList = i;
_freeCount++;
- _version++;
return true;
}
last = i;
i = entry.next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
}
}
return false;
@@ -721,27 +831,30 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
- if (_buckets != null)
+ int[] buckets = _buckets;
+ Entry[] entries = _entries;
+ int collisionCount = 0;
+ if (buckets != null)
{
int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF;
- int bucket = hashCode % _buckets.Length;
+ int bucket = hashCode % buckets.Length;
int last = -1;
- // Value in _buckets is 1-based
- int i = _buckets[bucket] - 1;
+ // Value in buckets is 1-based
+ int i = buckets[bucket] - 1;
while (i >= 0)
{
- ref Entry entry = ref _entries[i];
+ ref Entry entry = ref entries[i];
if (entry.hashCode == hashCode && (_comparer?.Equals(entry.key, key) ?? EqualityComparer<TKey>.Default.Equals(entry.key, key)))
{
if (last < 0)
{
- // Value in _buckets is 1-based
- _buckets[bucket] = entry.next + 1;
+ // Value in buckets is 1-based
+ buckets[bucket] = entry.next + 1;
}
else
{
- _entries[last].next = entry.next;
+ entries[last].next = entry.next;
}
value = entry.value;
@@ -751,23 +864,29 @@ namespace System.Collections.Generic
if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>())
{
- entry.key = default(TKey);
+ entry.key = default;
}
if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>())
{
- entry.value = default(TValue);
+ entry.value = default;
}
_freeList = i;
_freeCount++;
- _version++;
return true;
}
last = i;
i = entry.next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
}
}
- value = default(TValue);
+ value = default;
return false;
}
@@ -779,57 +898,37 @@ namespace System.Collections.Generic
value = _entries[i].value;
return true;
}
- value = default(TValue);
+ value = default;
return false;
}
- public bool TryAdd(TKey key, TValue value) => TryInsert(key, value, InsertionBehavior.None);
+ public bool TryAdd(TKey key, TValue value)
+ => TryInsert(key, value, InsertionBehavior.None);
- bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
- {
- get { return false; }
- }
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
- {
- CopyTo(array, index);
- }
+ => CopyTo(array, index);
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
- {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- }
-
if (array.Rank != 1)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
- }
-
if (array.GetLowerBound(0) != 0)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
- }
-
- if (index < 0 || index > array.Length)
- {
+ if ((uint)index > (uint)array.Length)
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
- }
-
if (array.Length - index < Count)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
- }
- KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[];
- if (pairs != null)
+ if (array is KeyValuePair<TKey, TValue>[] pairs)
{
CopyTo(pairs, index);
}
- else if (array is DictionaryEntry[])
+ else if (array is DictionaryEntry[] dictEntryArray)
{
- DictionaryEntry[] dictEntryArray = array as DictionaryEntry[];
Entry[] entries = _entries;
for (int i = 0; i < _count; i++)
{
@@ -867,9 +966,7 @@ namespace System.Collections.Generic
}
IEnumerator IEnumerable.GetEnumerator()
- {
- return new Enumerator(this, Enumerator.KeyValuePair);
- }
+ => new Enumerator(this, Enumerator.KeyValuePair);
/// <summary>
/// Ensures that the dictionary can hold up to 'capacity' entries without any further expansion of its backing storage
@@ -881,6 +978,7 @@ namespace System.Collections.Generic
int currentCapacity = _entries == null ? 0 : _entries.Length;
if (currentCapacity >= capacity)
return currentCapacity;
+ _version++;
if (_buckets == null)
return Initialize(capacity);
int newSize = HashHelpers.GetPrime(capacity);
@@ -900,9 +998,7 @@ namespace System.Collections.Generic
/// dictionary.TrimExcess();
/// </summary>
public void TrimExcess()
- {
- TrimExcess(Count);
- }
+ => TrimExcess(Count);
/// <summary>
/// Sets the capacity of this dictionary to hold up 'capacity' entries without any further expansion of its backing storage
@@ -922,6 +1018,7 @@ namespace System.Collections.Generic
return;
int oldCount = _count;
+ _version++;
Initialize(newSize);
Entry[] entries = _entries;
int[] buckets = _buckets;
@@ -945,10 +1042,7 @@ namespace System.Collections.Generic
_freeCount = 0;
}
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot
{
@@ -956,31 +1050,19 @@ namespace System.Collections.Generic
{
if (_syncRoot == null)
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
}
- bool IDictionary.IsFixedSize
- {
- get { return false; }
- }
+ bool IDictionary.IsFixedSize => false;
- bool IDictionary.IsReadOnly
- {
- get { return false; }
- }
+ bool IDictionary.IsReadOnly => false;
- ICollection IDictionary.Keys
- {
- get { return (ICollection)Keys; }
- }
+ ICollection IDictionary.Keys => (ICollection)Keys;
- ICollection IDictionary.Values
- {
- get { return (ICollection)Values; }
- }
+ ICollection IDictionary.Values => (ICollection)Values;
object IDictionary.this[object key]
{
@@ -1070,9 +1152,7 @@ namespace System.Collections.Generic
}
IDictionaryEnumerator IDictionary.GetEnumerator()
- {
- return new Enumerator(this, Enumerator.DictEntry);
- }
+ => new Enumerator(this, Enumerator.DictEntry);
void IDictionary.Remove(object key)
{
@@ -1088,11 +1168,11 @@ namespace System.Collections.Generic
public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>,
IDictionaryEnumerator
{
- private Dictionary<TKey, TValue> _dictionary;
- private int _version;
+ private readonly Dictionary<TKey, TValue> _dictionary;
+ private readonly int _version;
private int _index;
private KeyValuePair<TKey, TValue> _current;
- private int _getEnumeratorRetType; // What should Enumerator.Current return?
+ private readonly int _getEnumeratorRetType; // What should Enumerator.Current return?
internal const int DictEntry = 1;
internal const int KeyValuePair = 2;
@@ -1114,7 +1194,7 @@ namespace System.Collections.Generic
}
// Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
- // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
+ // dictionary.count+1 could be negative if dictionary.count is int.MaxValue
while ((uint)_index < (uint)_dictionary._count)
{
ref Entry entry = ref _dictionary._entries[_index++];
@@ -1131,10 +1211,7 @@ namespace System.Collections.Generic
return false;
}
- public KeyValuePair<TKey, TValue> Current
- {
- get { return _current; }
- }
+ public KeyValuePair<TKey, TValue> Current => _current;
public void Dispose()
{
@@ -1151,7 +1228,7 @@ namespace System.Collections.Generic
if (_getEnumeratorRetType == DictEntry)
{
- return new System.Collections.DictionaryEntry(_current.Key, _current.Value);
+ return new DictionaryEntry(_current.Key, _current.Value);
}
else
{
@@ -1230,9 +1307,7 @@ namespace System.Collections.Generic
}
public Enumerator GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
public void CopyTo(TKey[] array, int index)
{
@@ -1259,30 +1334,18 @@ namespace System.Collections.Generic
}
}
- public int Count
- {
- get { return _dictionary.Count; }
- }
+ public int Count => _dictionary.Count;
- bool ICollection<TKey>.IsReadOnly
- {
- get { return true; }
- }
+ bool ICollection<TKey>.IsReadOnly => true;
void ICollection<TKey>.Add(TKey item)
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
void ICollection<TKey>.Clear()
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
bool ICollection<TKey>.Contains(TKey item)
- {
- return _dictionary.ContainsKey(item);
- }
+ => _dictionary.ContainsKey(item);
bool ICollection<TKey>.Remove(TKey item)
{
@@ -1291,44 +1354,25 @@ namespace System.Collections.Generic
}
IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
IEnumerator IEnumerable.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
- {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- }
-
if (array.Rank != 1)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
- }
-
if (array.GetLowerBound(0) != 0)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
- }
-
- if (index < 0 || index > array.Length)
- {
+ if ((uint)index > (uint)array.Length)
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
- }
-
if (array.Length - index < _dictionary.Count)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
- }
- TKey[] keys = array as TKey[];
- if (keys != null)
+ if (array is TKey[] keys)
{
CopyTo(keys, index);
}
@@ -1356,24 +1400,18 @@ namespace System.Collections.Generic
}
}
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
- object ICollection.SyncRoot
- {
- get { return ((ICollection)_dictionary).SyncRoot; }
- }
+ object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
#if MONO
[Serializable]
#endif
- public struct Enumerator : IEnumerator<TKey>, System.Collections.IEnumerator
+ public struct Enumerator : IEnumerator<TKey>, IEnumerator
{
- private Dictionary<TKey, TValue> _dictionary;
+ private readonly Dictionary<TKey, TValue> _dictionary;
private int _index;
- private int _version;
+ private readonly int _version;
private TKey _currentKey;
internal Enumerator(Dictionary<TKey, TValue> dictionary)
@@ -1381,7 +1419,7 @@ namespace System.Collections.Generic
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
- _currentKey = default(TKey);
+ _currentKey = default;
}
public void Dispose()
@@ -1407,19 +1445,13 @@ namespace System.Collections.Generic
}
_index = _dictionary._count + 1;
- _currentKey = default(TKey);
+ _currentKey = default;
return false;
}
- public TKey Current
- {
- get
- {
- return _currentKey;
- }
- }
+ public TKey Current => _currentKey;
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -1432,7 +1464,7 @@ namespace System.Collections.Generic
}
}
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
@@ -1440,7 +1472,7 @@ namespace System.Collections.Generic
}
_index = 0;
- _currentKey = default(TKey);
+ _currentKey = default;
}
}
}
@@ -1464,9 +1496,7 @@ namespace System.Collections.Generic
}
public Enumerator GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
public void CopyTo(TValue[] array, int index)
{
@@ -1493,20 +1523,12 @@ namespace System.Collections.Generic
}
}
- public int Count
- {
- get { return _dictionary.Count; }
- }
+ public int Count => _dictionary.Count;
- bool ICollection<TValue>.IsReadOnly
- {
- get { return true; }
- }
+ bool ICollection<TValue>.IsReadOnly => true;
void ICollection<TValue>.Add(TValue item)
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
bool ICollection<TValue>.Remove(TValue item)
{
@@ -1515,52 +1537,31 @@ namespace System.Collections.Generic
}
void ICollection<TValue>.Clear()
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
bool ICollection<TValue>.Contains(TValue item)
- {
- return _dictionary.ContainsValue(item);
- }
+ => _dictionary.ContainsValue(item);
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
IEnumerator IEnumerable.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
- {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- }
-
if (array.Rank != 1)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
- }
-
if (array.GetLowerBound(0) != 0)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
- }
-
- if (index < 0 || index > array.Length)
- {
+ if ((uint)index > (uint)array.Length)
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
- }
-
if (array.Length - index < _dictionary.Count)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
- TValue[] values = array as TValue[];
- if (values != null)
+ if (array is TValue[] values)
{
CopyTo(values, index);
}
@@ -1588,24 +1589,18 @@ namespace System.Collections.Generic
}
}
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
- object ICollection.SyncRoot
- {
- get { return ((ICollection)_dictionary).SyncRoot; }
- }
+ object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
#if MONO
[Serializable]
#endif
- public struct Enumerator : IEnumerator<TValue>, System.Collections.IEnumerator
+ public struct Enumerator : IEnumerator<TValue>, IEnumerator
{
- private Dictionary<TKey, TValue> _dictionary;
+ private readonly Dictionary<TKey, TValue> _dictionary;
private int _index;
- private int _version;
+ private readonly int _version;
private TValue _currentValue;
internal Enumerator(Dictionary<TKey, TValue> dictionary)
@@ -1613,7 +1608,7 @@ namespace System.Collections.Generic
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
- _currentValue = default(TValue);
+ _currentValue = default;
}
public void Dispose()
@@ -1638,19 +1633,13 @@ namespace System.Collections.Generic
}
}
_index = _dictionary._count + 1;
- _currentValue = default(TValue);
+ _currentValue = default;
return false;
}
- public TValue Current
- {
- get
- {
- return _currentValue;
- }
- }
+ public TValue Current => _currentValue;
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -1663,14 +1652,14 @@ namespace System.Collections.Generic
}
}
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
_index = 0;
- _currentValue = default(TValue);
+ _currentValue = default;
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs
index 48eddb874..3990e1378 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs
@@ -17,13 +17,13 @@ namespace System.Collections.Generic
HResult = HResults.COR_E_KEYNOTFOUND;
}
- public KeyNotFoundException(String message)
+ public KeyNotFoundException(string message)
: base(message)
{
HResult = HResults.COR_E_KEYNOTFOUND;
}
- public KeyNotFoundException(String message, Exception innerException)
+ public KeyNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_KEYNOTFOUND;
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
index 56bbea895..698abe9cf 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
@@ -5,6 +5,7 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Threading;
namespace System.Collections.Generic
{
@@ -17,8 +18,8 @@ namespace System.Collections.Generic
[DebuggerTypeProxy(typeof(ICollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class List<T> : IList<T>, IList, IReadOnlyList<T>
{
private const int DefaultCapacity = 4;
@@ -63,8 +64,7 @@ namespace System.Collections.Generic
if (collection == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
- ICollection<T> c = collection as ICollection<T>;
- if (c != null)
+ if (collection is ICollection<T> c)
{
int count = c.Count;
if (count == 0)
@@ -123,44 +123,26 @@ namespace System.Collections.Generic
}
// Read-only property describing how many elements are in the List.
- public int Count
- {
- get
- {
- return _size;
- }
- }
+ public int Count => _size;
- bool System.Collections.IList.IsFixedSize
- {
- get { return false; }
- }
+ bool IList.IsFixedSize => false;
// Is this List read-only?
- bool ICollection<T>.IsReadOnly
- {
- get { return false; }
- }
+ bool ICollection<T>.IsReadOnly => false;
- bool System.Collections.IList.IsReadOnly
- {
- get { return false; }
- }
+ bool IList.IsReadOnly => false;
// Is this List synchronized (thread-safe)?
- bool System.Collections.ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
// Synchronization root for this object.
- object System.Collections.ICollection.SyncRoot
+ object ICollection.SyncRoot
{
get
{
if (_syncRoot == null)
{
- System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
+ Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
@@ -197,7 +179,7 @@ namespace System.Collections.Generic
return ((value is T) || (value == null && default(T) == null));
}
- object System.Collections.IList.this[int index]
+ object IList.this[int index]
{
get
{
@@ -225,9 +207,9 @@ namespace System.Collections.Generic
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T item)
{
- var array = _items;
- var size = _size;
_version++;
+ T[] array = _items;
+ int size = _size;
if ((uint)size < (uint)array.Length)
{
_size = size + 1;
@@ -243,13 +225,13 @@ namespace System.Collections.Generic
[MethodImpl(MethodImplOptions.NoInlining)]
private void AddWithResize(T item)
{
- var size = _size;
+ int size = _size;
EnsureCapacity(size + 1);
_size = size + 1;
_items[size] = item;
}
- int System.Collections.IList.Add(Object item)
+ int IList.Add(object item)
{
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
@@ -270,14 +252,10 @@ namespace System.Collections.Generic
// capacity or the new size, whichever is larger.
//
public void AddRange(IEnumerable<T> collection)
- {
- InsertRange(_size, collection);
- }
+ => InsertRange(_size, collection);
public ReadOnlyCollection<T> AsReadOnly()
- {
- return new ReadOnlyCollection<T>(this);
- }
+ => new ReadOnlyCollection<T>(this);
// Searches a section of the list for a given element using a binary search
// algorithm. Elements of the list are compared to the search value using
@@ -312,25 +290,20 @@ namespace System.Collections.Generic
}
public int BinarySearch(T item)
- {
- return BinarySearch(0, Count, item, null);
- }
+ => BinarySearch(0, Count, item, null);
public int BinarySearch(T item, IComparer<T> comparer)
- {
- return BinarySearch(0, Count, item, comparer);
- }
-
+ => BinarySearch(0, Count, item, comparer);
// Clears the contents of List.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
+ _version++;
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
int size = _size;
_size = 0;
- _version++;
if (size > 0)
{
Array.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references.
@@ -339,7 +312,6 @@ namespace System.Collections.Generic
else
{
_size = 0;
- _version++;
}
}
@@ -360,7 +332,7 @@ namespace System.Collections.Generic
return _size != 0 && IndexOf(item) != -1;
}
- bool System.Collections.IList.Contains(object item)
+ bool IList.Contains(object item)
{
if (IsCompatibleObject(item))
{
@@ -388,13 +360,11 @@ namespace System.Collections.Generic
// Copies this List into array, which must be of a
// compatible array type.
public void CopyTo(T[] array)
- {
- CopyTo(array, 0);
- }
+ => CopyTo(array, 0);
// Copies this List into array, which must be of a
// compatible array type.
- void System.Collections.ICollection.CopyTo(Array array, int arrayIndex)
+ void ICollection.CopyTo(Array array, int arrayIndex)
{
if ((array != null) && (array.Rank != 1))
{
@@ -452,9 +422,7 @@ namespace System.Collections.Generic
}
public bool Exists(Predicate<T> match)
- {
- return FindIndex(match) != -1;
- }
+ => FindIndex(match) != -1;
public T Find(Predicate<T> match)
{
@@ -470,7 +438,7 @@ namespace System.Collections.Generic
return _items[i];
}
}
- return default(T);
+ return default;
}
public List<T> FindAll(Predicate<T> match)
@@ -492,14 +460,10 @@ namespace System.Collections.Generic
}
public int FindIndex(Predicate<T> match)
- {
- return FindIndex(0, _size, match);
- }
+ => FindIndex(0, _size, match);
public int FindIndex(int startIndex, Predicate<T> match)
- {
- return FindIndex(startIndex, _size - startIndex, match);
- }
+ => FindIndex(startIndex, _size - startIndex, match);
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
@@ -540,18 +504,14 @@ namespace System.Collections.Generic
return _items[i];
}
}
- return default(T);
+ return default;
}
public int FindLastIndex(Predicate<T> match)
- {
- return FindLastIndex(_size - 1, _size, match);
- }
+ => FindLastIndex(_size - 1, _size, match);
public int FindLastIndex(int startIndex, Predicate<T> match)
- {
- return FindLastIndex(startIndex, startIndex + 1, match);
- }
+ => FindLastIndex(startIndex, startIndex + 1, match);
public int FindLastIndex(int startIndex, int count, Predicate<T> match)
{
@@ -622,19 +582,13 @@ namespace System.Collections.Generic
// GetObject methods of the enumerator will throw an exception.
//
public Enumerator GetEnumerator()
- {
- return new Enumerator(this);
- }
+ => new Enumerator(this);
IEnumerator<T> IEnumerable<T>.GetEnumerator()
- {
- return new Enumerator(this);
- }
+ => new Enumerator(this);
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return new Enumerator(this);
- }
+ IEnumerator IEnumerable.GetEnumerator()
+ => new Enumerator(this);
public List<T> GetRange(int index, int count)
{
@@ -669,11 +623,9 @@ namespace System.Collections.Generic
// search.
//
public int IndexOf(T item)
- {
- return Array.IndexOf(_items, item, 0, _size);
- }
+ => Array.IndexOf(_items, item, 0, _size);
- int System.Collections.IList.IndexOf(object item)
+ int IList.IndexOf(object item)
{
if (IsCompatibleObject(item))
{
@@ -739,7 +691,7 @@ namespace System.Collections.Generic
_version++;
}
- void System.Collections.IList.Insert(int index, Object item)
+ void IList.Insert(int index, object item)
{
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
@@ -770,9 +722,8 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
}
- ICollection<T> c = collection as ICollection<T>;
- if (c != null)
- { // if collection is ICollection<T>
+ if (collection is ICollection<T> c)
+ {
int count = c.Count;
if (count > 0)
{
@@ -905,7 +856,7 @@ namespace System.Collections.Generic
return false;
}
- void System.Collections.IList.Remove(object item)
+ void IList.Remove(object item)
{
if (IsCompatibleObject(item))
{
@@ -967,7 +918,7 @@ namespace System.Collections.Generic
}
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
- _items[_size] = default(T);
+ _items[_size] = default;
}
_version++;
}
@@ -990,7 +941,6 @@ namespace System.Collections.Generic
if (count > 0)
{
- int i = _size;
_size -= count;
if (index < _size)
{
@@ -1007,9 +957,7 @@ namespace System.Collections.Generic
// Reverses the elements in this list.
public void Reverse()
- {
- Reverse(0, Count);
- }
+ => Reverse(0, Count);
// Reverses the elements in a range of this list. Following a call to this
// method, an element in the range given by index and count
@@ -1041,16 +989,12 @@ namespace System.Collections.Generic
// Sorts the elements in this list. Uses the default comparer and
// Array.Sort.
public void Sort()
- {
- Sort(0, Count, null);
- }
+ => Sort(0, Count, null);
// Sorts the elements in this list. Uses Array.Sort with the
// provided comparer.
public void Sort(IComparer<T> comparer)
- {
- Sort(0, Count, comparer);
- }
+ => Sort(0, Count, comparer);
// Sorts the elements in a section of this list. The sort compares the
// elements to each other using the given IComparer interface. If
@@ -1150,9 +1094,9 @@ namespace System.Collections.Generic
Debug.Assert(enumerable != null);
Debug.Assert(!(enumerable is ICollection<T>), "We should have optimized for this beforehand.");
+ _version++; // Even if the enumerable has no items, we can update _version.
using (IEnumerator<T> en = enumerable.GetEnumerator())
{
- _version++; // Even if the enumerable has no items, we can update _version.
while (en.MoveNext())
{
@@ -1170,11 +1114,11 @@ namespace System.Collections.Generic
}
}
- public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
+ public struct Enumerator : IEnumerator<T>, IEnumerator
{
- private List<T> _list;
+ private readonly List<T> _list;
private int _index;
- private int _version;
+ private readonly int _version;
private T _current;
internal Enumerator(List<T> list)
@@ -1182,7 +1126,7 @@ namespace System.Collections.Generic
_list = list;
_index = 0;
_version = list._version;
- _current = default(T);
+ _current = default;
}
public void Dispose()
@@ -1210,19 +1154,13 @@ namespace System.Collections.Generic
}
_index = _list._size + 1;
- _current = default(T);
+ _current = default;
return false;
}
- public T Current
- {
- get
- {
- return _current;
- }
- }
+ public T Current => _current;
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -1234,7 +1172,7 @@ namespace System.Collections.Generic
}
}
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _list._version)
{
@@ -1242,7 +1180,7 @@ namespace System.Collections.Generic
}
_index = 0;
- _current = default(T);
+ _current = default;
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
index 72f62c2b9..91b782061 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
@@ -11,12 +11,8 @@ namespace System.Collections.Generic
// keeps the performance not affected till we hit collision threshold and then we switch to the comparer which is using
// randomized string hashing.
[Serializable] // Required for compatibility with .NET Core 2.0 as we exposed the NonRandomizedStringEqualityComparer inside the serialization blob
-#if CORERT
- public
-#else
- internal
-#endif
- sealed class NonRandomizedStringEqualityComparer : EqualityComparer<string>, ISerializable
+ // Needs to be public to support binary serialization compatibility
+ public sealed class NonRandomizedStringEqualityComparer : EqualityComparer<string>, ISerializable
{
internal static new IEqualityComparer<string> Default { get; } = new NonRandomizedStringEqualityComparer();
@@ -27,7 +23,7 @@ namespace System.Collections.Generic
public sealed override bool Equals(string x, string y) => string.Equals(x, y);
- public sealed override int GetHashCode(string obj) => obj?.GetLegacyNonRandomizedHashCode() ?? 0;
+ public sealed override int GetHashCode(string obj) => obj?.GetNonRandomizedHashCode() ?? 0;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs
index 72da4a9e1..aea6052f0 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs
@@ -21,7 +21,16 @@ namespace System.Collections.Generic
_pos = 0;
}
- public int Length => _pos;
+ public int Length
+ {
+ get => _pos;
+ set
+ {
+ Debug.Assert(value >= 0);
+ Debug.Assert(value <= _span.Length);
+ _pos = value;
+ }
+ }
public ref T this[int index]
{
diff --git a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs
new file mode 100644
index 000000000..d91dfd878
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs
@@ -0,0 +1,29 @@
+// 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.
+
+// Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo
+// object until OnDeserialization is called.
+
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+
+namespace System.Collections
+{
+ internal static partial class HashHelpers
+ {
+ private static ConditionalWeakTable<object, SerializationInfo> s_serializationInfoTable;
+
+ public static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
+ {
+ get
+ {
+ if (s_serializationInfoTable == null)
+ Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null);
+
+ return s_serializationInfoTable;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs
index 49cff85b5..ba2c75c89 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs
@@ -2,17 +2,18 @@
// 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.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-using System.Threading;
namespace System.Collections
{
- internal static class HashHelpers
+ internal static partial class HashHelpers
{
public const int HashCollisionThreshold = 100;
+ // This is the maximum prime smaller than Array.MaxArrayLength
+ public const int MaxPrimeArrayLength = 0x7FEFFFFD;
+
public const int HashPrime = 101;
// Table of prime numbers to use as hash table sizes.
@@ -26,12 +27,14 @@ namespace System.Collections
// hashtable operations such as add. Having a prime guarantees that double
// hashing does not lead to infinite loops. IE, your hash function will be
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
+ // We prefer the low computation costs of higher prime numbers over the increased
+ // memory allocation of a fixed prime number i.e. when right sizing a HashSet.
public static readonly int[] primes = {
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
- 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
+ 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 };
public static bool IsPrime(int candidate)
{
@@ -56,12 +59,13 @@ namespace System.Collections
for (int i = 0; i < primes.Length; i++)
{
int prime = primes[i];
- if (prime >= min) return prime;
+ if (prime >= min)
+ return prime;
}
//outside of our predefined table.
//compute the hard way.
- for (int i = (min | 1); i < Int32.MaxValue; i += 2)
+ for (int i = (min | 1); i < int.MaxValue; i += 2)
{
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
return i;
@@ -74,7 +78,7 @@ namespace System.Collections
{
int newSize = 2 * oldSize;
- // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
+ // Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
{
@@ -84,25 +88,5 @@ namespace System.Collections
return GetPrime(newSize);
}
-
-
- // This is the maximum prime smaller than Array.MaxArrayLength
- public const int MaxPrimeArrayLength = 0x7FEFFFFD;
-
-
- // Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo
- // object until OnDeserialization is called.
- private static ConditionalWeakTable<object, SerializationInfo> s_serializationInfoTable;
-
- internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
- {
- get
- {
- if (s_serializationInfoTable == null)
- Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null);
-
- return s_serializationInfoTable;
- }
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs b/src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs
new file mode 100644
index 000000000..1c3139d27
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs
@@ -0,0 +1,1650 @@
+// 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.
+
+/*============================================================
+**
+** Class: Hashtable
+**
+** Purpose: Represents a collection of key/value pairs
+** that are organized based on the hash code
+** of the key.
+**
+===========================================================*/
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.Threading;
+
+namespace System.Collections
+{
+ // The Hashtable class represents a dictionary of associated keys and values
+ // with constant lookup time.
+ //
+ // Objects used as keys in a hashtable must implement the GetHashCode
+ // and Equals methods (or they can rely on the default implementations
+ // inherited from Object if key equality is simply reference
+ // equality). Furthermore, the GetHashCode and Equals methods of
+ // a key object must produce the same results given the same parameters for the
+ // entire time the key is present in the hashtable. In practical terms, this
+ // means that key objects should be immutable, at least for the time they are
+ // used as keys in a hashtable.
+ //
+ // When entries are added to a hashtable, they are placed into
+ // buckets based on the hashcode of their keys. Subsequent lookups of
+ // keys will use the hashcode of the keys to only search a particular bucket,
+ // thus substantially reducing the number of key comparisons required to find
+ // an entry. A hashtable's maximum load factor, which can be specified
+ // when the hashtable is instantiated, determines the maximum ratio of
+ // hashtable entries to hashtable buckets. Smaller load factors cause faster
+ // average lookup times at the cost of increased memory consumption. The
+ // default maximum load factor of 1.0 generally provides the best balance
+ // between speed and size. As entries are added to a hashtable, the hashtable's
+ // actual load factor increases, and when the actual load factor reaches the
+ // maximum load factor value, the number of buckets in the hashtable is
+ // automatically increased by approximately a factor of two (to be precise, the
+ // number of hashtable buckets is increased to the smallest prime number that
+ // is larger than twice the current number of hashtable buckets).
+ //
+ // Each object provides their own hash function, accessed by calling
+ // GetHashCode(). However, one can write their own object
+ // implementing IEqualityComparer and pass it to a constructor on
+ // the Hashtable. That hash function (and the equals method on the
+ // IEqualityComparer) would be used for all objects in the table.
+ //
+ [DebuggerTypeProxy(typeof(System.Collections.Hashtable.HashtableDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable
+ {
+ /*
+ This Hashtable uses double hashing. There are hashsize buckets in the
+ table, and each bucket can contain 0 or 1 element. We use a bit to mark
+ whether there's been a collision when we inserted multiple elements
+ (ie, an inserted item was hashed at least a second time and we probed
+ this bucket, but it was already in use). Using the collision bit, we
+ can terminate lookups & removes for elements that aren't in the hash
+ table more quickly. We steal the most significant bit from the hash code
+ to store the collision bit.
+
+ Our hash function is of the following form:
+
+ h(key, n) = h1(key) + n*h2(key)
+
+ where n is the number of times we've hit a collided bucket and rehashed
+ (on this particular lookup). Here are our hash functions:
+
+ h1(key) = GetHash(key); // default implementation calls key.GetHashCode();
+ h2(key) = 1 + (((h1(key) >> 5) + 1) % (hashsize - 1));
+
+ The h1 can return any number. h2 must return a number between 1 and
+ hashsize - 1 that is relatively prime to hashsize (not a problem if
+ hashsize is prime). (Knuth's Art of Computer Programming, Vol. 3, p. 528-9)
+ If this is true, then we are guaranteed to visit every bucket in exactly
+ hashsize probes, since the least common multiple of hashsize and h2(key)
+ will be hashsize * h2(key). (This is the first number where adding h2 to
+ h1 mod hashsize will be 0 and we will search the same bucket twice).
+
+ We previously used a different h2(key, n) that was not constant. That is a
+ horrifically bad idea, unless you can prove that series will never produce
+ any identical numbers that overlap when you mod them by hashsize, for all
+ subranges from i to i+hashsize, for all i. It's not worth investigating,
+ since there was no clear benefit from using that hash function, and it was
+ broken.
+
+ For efficiency reasons, we've implemented this by storing h1 and h2 in a
+ temporary, and setting a variable called seed equal to h1. We do a probe,
+ and if we collided, we simply add h2 to seed each time through the loop.
+
+ A good test for h2() is to subclass Hashtable, provide your own implementation
+ of GetHash() that returns a constant, then add many items to the hash table.
+ Make sure Count equals the number of items you inserted.
+
+ Note that when we remove an item from the hash table, we set the key
+ equal to buckets, if there was a collision in this bucket. Otherwise
+ we'd either wipe out the collision bit, or we'd still have an item in
+ the hash table.
+
+ --
+ */
+
+ private const int InitialSize = 3;
+
+ private const string LoadFactorName = "LoadFactor"; // Do not rename (binary serialization)
+ private const string VersionName = "Version"; // Do not rename (binary serialization)
+ private const string ComparerName = "Comparer"; // Do not rename (binary serialization)
+ private const string HashCodeProviderName = "HashCodeProvider"; // Do not rename (binary serialization)
+ private const string HashSizeName = "HashSize"; // Must save buckets.Length. Do not rename (binary serialization)
+ private const string KeysName = "Keys"; // Do not rename (binary serialization)
+ private const string ValuesName = "Values"; // Do not rename (binary serialization)
+ private const string KeyComparerName = "KeyComparer"; // Do not rename (binary serialization)
+
+ // Deleted entries have their key set to buckets
+
+ // The hash table data.
+ // This cannot be serialized
+ private struct bucket
+ {
+ public object key;
+ public object val;
+ public int hash_coll; // Store hash code; sign bit means there was a collision.
+ }
+
+ private bucket[] _buckets;
+
+ // The total number of entries in the hash table.
+ private int _count;
+
+ // The total number of collision bits set in the hashtable
+ private int _occupancy;
+
+ private int _loadsize;
+ private float _loadFactor;
+
+ private volatile int _version;
+ private volatile bool _isWriterInProgress;
+
+ private ICollection _keys;
+ private ICollection _values;
+
+ private IEqualityComparer _keycomparer;
+ private object _syncRoot;
+
+ [Obsolete("Please use EqualityComparer property.")]
+ protected IHashCodeProvider hcp
+ {
+ get
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ return ((CompatibleComparer)_keycomparer).HashCodeProvider;
+ }
+ else if (_keycomparer == null)
+ {
+ return null;
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ set
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
+ _keycomparer = new CompatibleComparer(value, keyComparer.Comparer);
+ }
+ else if (_keycomparer == null)
+ {
+ _keycomparer = new CompatibleComparer(value, (IComparer)null);
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ }
+
+ [Obsolete("Please use KeyComparer properties.")]
+ protected IComparer comparer
+ {
+ get
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ return ((CompatibleComparer)_keycomparer).Comparer;
+ }
+ else if (_keycomparer == null)
+ {
+ return null;
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ set
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
+ _keycomparer = new CompatibleComparer(keyComparer.HashCodeProvider, value);
+ }
+ else if (_keycomparer == null)
+ {
+ _keycomparer = new CompatibleComparer((IHashCodeProvider)null, value);
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ }
+
+
+ protected IEqualityComparer EqualityComparer
+ {
+ get
+ {
+ return _keycomparer;
+ }
+ }
+
+ // Note: this constructor is a bogus constructor that does nothing
+ // and is for use only with SyncHashtable.
+ internal Hashtable(bool trash)
+ {
+ }
+
+ // Constructs a new hashtable. The hashtable is created with an initial
+ // capacity of zero and a load factor of 1.0.
+ public Hashtable() : this(0, 1.0f)
+ {
+ }
+
+ // Constructs a new hashtable with the given initial capacity and a load
+ // factor of 1.0. The capacity argument serves as an indication of
+ // the number of entries the hashtable will contain. When this number (or
+ // an approximation) is known, specifying it in the constructor can
+ // eliminate a number of resizing operations that would otherwise be
+ // performed when elements are added to the hashtable.
+ //
+ public Hashtable(int capacity) : this(capacity, 1.0f)
+ {
+ }
+
+ // Constructs a new hashtable with the given initial capacity and load
+ // factor. The capacity argument serves as an indication of the
+ // number of entries the hashtable will contain. When this number (or an
+ // approximation) is known, specifying it in the constructor can eliminate
+ // a number of resizing operations that would otherwise be performed when
+ // elements are added to the hashtable. The loadFactor argument
+ // indicates the maximum ratio of hashtable entries to hashtable buckets.
+ // Smaller load factors cause faster average lookup times at the cost of
+ // increased memory consumption. A load factor of 1.0 generally provides
+ // the best balance between speed and size.
+ //
+ public Hashtable(int capacity, float loadFactor)
+ {
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (!(loadFactor >= 0.1f && loadFactor <= 1.0f))
+ throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.Format(SR.ArgumentOutOfRange_HashtableLoadFactor, .1, 1.0));
+
+ // Based on perf work, .72 is the optimal load factor for this table.
+ _loadFactor = 0.72f * loadFactor;
+
+ double rawsize = capacity / _loadFactor;
+ if (rawsize > int.MaxValue)
+ throw new ArgumentException(SR.Arg_HTCapacityOverflow, nameof(capacity));
+
+ // Avoid awfully small sizes
+ int hashsize = (rawsize > InitialSize) ? HashHelpers.GetPrime((int)rawsize) : InitialSize;
+ _buckets = new bucket[hashsize];
+
+ _loadsize = (int)(_loadFactor * hashsize);
+ _isWriterInProgress = false;
+ // Based on the current algorithm, loadsize must be less than hashsize.
+ Debug.Assert(_loadsize < hashsize, "Invalid hashtable loadsize!");
+ }
+
+ public Hashtable(int capacity, float loadFactor, IEqualityComparer equalityComparer) : this(capacity, loadFactor)
+ {
+ _keycomparer = equalityComparer;
+ }
+
+ [Obsolete("Please use Hashtable(IEqualityComparer) instead.")]
+ public Hashtable(IHashCodeProvider hcp, IComparer comparer)
+ : this(0, 1.0f, hcp, comparer)
+ {
+ }
+
+ public Hashtable(IEqualityComparer equalityComparer) : this(0, 1.0f, equalityComparer)
+ {
+ }
+
+ [Obsolete("Please use Hashtable(int, IEqualityComparer) instead.")]
+ public Hashtable(int capacity, IHashCodeProvider hcp, IComparer comparer)
+ : this(capacity, 1.0f, hcp, comparer)
+ {
+ }
+
+ public Hashtable(int capacity, IEqualityComparer equalityComparer)
+ : this(capacity, 1.0f, equalityComparer)
+ {
+ }
+
+ // Constructs a new hashtable containing a copy of the entries in the given
+ // dictionary. The hashtable is created with a load factor of 1.0.
+ //
+ public Hashtable(IDictionary d) : this(d, 1.0f)
+ {
+ }
+
+ // Constructs a new hashtable containing a copy of the entries in the given
+ // dictionary. The hashtable is created with the given load factor.
+ //
+ public Hashtable(IDictionary d, float loadFactor)
+ : this(d, loadFactor, (IEqualityComparer)null)
+ {
+ }
+
+ [Obsolete("Please use Hashtable(IDictionary, IEqualityComparer) instead.")]
+ public Hashtable(IDictionary d, IHashCodeProvider hcp, IComparer comparer)
+ : this(d, 1.0f, hcp, comparer)
+ {
+ }
+
+ public Hashtable(IDictionary d, IEqualityComparer equalityComparer)
+ : this(d, 1.0f, equalityComparer)
+ {
+ }
+
+ [Obsolete("Please use Hashtable(int, float, IEqualityComparer) instead.")]
+ public Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
+ : this(capacity, loadFactor)
+ {
+ if (hcp != null || comparer != null)
+ {
+ _keycomparer = new CompatibleComparer(hcp, comparer);
+ }
+ }
+
+ [Obsolete("Please use Hashtable(IDictionary, float, IEqualityComparer) instead.")]
+ public Hashtable(IDictionary d, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
+ : this((d != null ? d.Count : 0), loadFactor, hcp, comparer)
+ {
+ if (d == null)
+ throw new ArgumentNullException(nameof(d), SR.ArgumentNull_Dictionary);
+
+ IDictionaryEnumerator e = d.GetEnumerator();
+ while (e.MoveNext())
+ Add(e.Key, e.Value);
+ }
+
+ public Hashtable(IDictionary d, float loadFactor, IEqualityComparer equalityComparer)
+ : this((d != null ? d.Count : 0), loadFactor, equalityComparer)
+ {
+ if (d == null)
+ throw new ArgumentNullException(nameof(d), SR.ArgumentNull_Dictionary);
+
+ IDictionaryEnumerator e = d.GetEnumerator();
+ while (e.MoveNext())
+ Add(e.Key, e.Value);
+ }
+
+ protected Hashtable(SerializationInfo info, StreamingContext context)
+ {
+ //We can't do anything with the keys and values until the entire graph has been deserialized
+ //and we have a reasonable estimate that GetHashCode is not going to fail. For the time being,
+ //we'll just cache this. The graph is not valid until OnDeserialization has been called.
+ HashHelpers.SerializationInfoTable.Add(this, info);
+ }
+
+ // ?InitHash? is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
+ //
+ // 1) The only ?correctness? requirement is that the ?increment? used to probe
+ // a. Be non-zero
+ // b. Be relatively prime to the table size ?hashSize?. (This is needed to insure you probe all entries in the table before you ?wrap? and visit entries already probed)
+ // 2) Because we choose table sizes to be primes, we just need to insure that the increment is 0 < incr < hashSize
+ //
+ // Thus this function would work: Incr = 1 + (seed % (hashSize-1))
+ //
+ // While this works well for ?uniformly distributed? keys, in practice, non-uniformity is common.
+ // In particular in practice we can see ?mostly sequential? where you get long clusters of keys that ?pack?.
+ // To avoid bad behavior you want it to be the case that the increment is ?large? even for ?small? values (because small
+ // values tend to happen more in practice). Thus we multiply ?seed? by a number that will make these small values
+ // bigger (and not hurt large values). We picked HashPrime (101) because it was prime, and if ?hashSize-1? is not a multiple of HashPrime
+ // (enforced in GetPrime), then incr has the potential of being every value from 1 to hashSize-1. The choice was largely arbitrary.
+ //
+ // Computes the hash function: H(key, i) = h1(key) + i*h2(key, hashSize).
+ // The out parameter seed is h1(key), while the out parameter
+ // incr is h2(key, hashSize). Callers of this function should
+ // add incr each time through a loop.
+ private uint InitHash(object key, int hashsize, out uint seed, out uint incr)
+ {
+ // Hashcode must be positive. Also, we must not use the sign bit, since
+ // that is used for the collision bit.
+ uint hashcode = (uint)GetHash(key) & 0x7FFFFFFF;
+ seed = (uint)hashcode;
+ // Restriction: incr MUST be between 1 and hashsize - 1, inclusive for
+ // the modular arithmetic to work correctly. This guarantees you'll
+ // visit every bucket in the table exactly once within hashsize
+ // iterations. Violate this and it'll cause obscure bugs forever.
+ // If you change this calculation for h2(key), update putEntry too!
+ incr = (uint)(1 + ((seed * HashHelpers.HashPrime) % ((uint)hashsize - 1)));
+ return hashcode;
+ }
+
+ // Adds an entry with the given key and value to this hashtable. An
+ // ArgumentException is thrown if the key is null or if the key is already
+ // present in the hashtable.
+ //
+ public virtual void Add(object key, object value)
+ {
+ Insert(key, value, true);
+ }
+
+ // Removes all entries from this hashtable.
+ public virtual void Clear()
+ {
+ Debug.Assert(!_isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
+
+ if (_count == 0 && _occupancy == 0)
+ return;
+
+ _isWriterInProgress = true;
+ for (int i = 0; i < _buckets.Length; i++)
+ {
+ _buckets[i].hash_coll = 0;
+ _buckets[i].key = null;
+ _buckets[i].val = null;
+ }
+
+ _count = 0;
+ _occupancy = 0;
+ UpdateVersion();
+ _isWriterInProgress = false;
+ }
+
+ // Clone returns a virtually identical copy of this hash table. This does
+ // a shallow copy - the Objects in the table aren't cloned, only the references
+ // to those Objects.
+ public virtual object Clone()
+ {
+ bucket[] lbuckets = _buckets;
+ Hashtable ht = new Hashtable(_count, _keycomparer);
+ ht._version = _version;
+ ht._loadFactor = _loadFactor;
+ ht._count = 0;
+
+ int bucket = lbuckets.Length;
+ while (bucket > 0)
+ {
+ bucket--;
+ object keyv = lbuckets[bucket].key;
+ if ((keyv != null) && (keyv != lbuckets))
+ {
+ ht[keyv] = lbuckets[bucket].val;
+ }
+ }
+
+ return ht;
+ }
+
+ // Checks if this hashtable contains the given key.
+ public virtual bool Contains(object key)
+ {
+ return ContainsKey(key);
+ }
+
+ // Checks if this hashtable contains an entry with the given key. This is
+ // an O(1) operation.
+ //
+ public virtual bool ContainsKey(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ uint seed;
+ uint incr;
+ // Take a snapshot of buckets, in case another thread resizes table
+ bucket[] lbuckets = _buckets;
+ uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bucketNumber = (int)(seed % (uint)lbuckets.Length);
+ do
+ {
+ b = lbuckets[bucketNumber];
+ if (b.key == null)
+ {
+ return false;
+ }
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(b.key, key))
+ return true;
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)lbuckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
+ return false;
+ }
+
+
+
+ // Checks if this hashtable contains an entry with the given value. The
+ // values of the entries of the hashtable are compared to the given value
+ // using the Object.Equals method. This method performs a linear
+ // search and is thus be substantially slower than the ContainsKey
+ // method.
+ //
+ public virtual bool ContainsValue(object value)
+ {
+ if (value == null)
+ {
+ for (int i = _buckets.Length; --i >= 0;)
+ {
+ if (_buckets[i].key != null && _buckets[i].key != _buckets && _buckets[i].val == null)
+ return true;
+ }
+ }
+ else
+ {
+ for (int i = _buckets.Length; --i >= 0;)
+ {
+ object val = _buckets[i].val;
+ if (val != null && val.Equals(value))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Copies the keys of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the KeyCollection class.
+ private void CopyKeys(Array array, int arrayIndex)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(array.Rank == 1);
+
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ array.SetValue(keyv, arrayIndex++);
+ }
+ }
+ }
+
+ // Copies the keys of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the KeyCollection class.
+ private void CopyEntries(Array array, int arrayIndex)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(array.Rank == 1);
+
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ DictionaryEntry entry = new DictionaryEntry(keyv, lbuckets[i].val);
+ array.SetValue(entry, arrayIndex++);
+ }
+ }
+ }
+
+ // Copies the values in this hash table to an array at
+ // a given index. Note that this only copies values, and not keys.
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), SR.ArgumentNull_Array);
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - arrayIndex < Count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ CopyEntries(array, arrayIndex);
+ }
+
+ // Copies the values in this Hashtable to an KeyValuePairs array.
+ // KeyValuePairs is different from Dictionary Entry in that it has special
+ // debugger attributes on its fields.
+
+ internal virtual KeyValuePairs[] ToKeyValuePairsArray()
+ {
+ KeyValuePairs[] array = new KeyValuePairs[_count];
+ int index = 0;
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ array[index++] = new KeyValuePairs(keyv, lbuckets[i].val);
+ }
+ }
+
+ return array;
+ }
+
+
+ // Copies the values of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the ValueCollection class.
+ private void CopyValues(Array array, int arrayIndex)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(array.Rank == 1);
+
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ array.SetValue(lbuckets[i].val, arrayIndex++);
+ }
+ }
+ }
+
+ // Returns the value associated with the given key. If an entry with the
+ // given key is not found, the returned value is null.
+ //
+ public virtual object this[object key]
+ {
+ get
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ uint seed;
+ uint incr;
+
+
+ // Take a snapshot of buckets, in case another thread does a resize
+ bucket[] lbuckets = _buckets;
+ uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bucketNumber = (int)(seed % (uint)lbuckets.Length);
+ do
+ {
+ int currentversion;
+
+ // A read operation on hashtable has three steps:
+ // (1) calculate the hash and find the slot number.
+ // (2) compare the hashcode, if equal, go to step 3. Otherwise end.
+ // (3) compare the key, if equal, go to step 4. Otherwise end.
+ // (4) return the value contained in the bucket.
+ // After step 3 and before step 4. A writer can kick in a remove the old item and add a new one
+ // in the same bucket. So in the reader we need to check if the hash table is modified during above steps.
+ //
+ // Writers (Insert, Remove, Clear) will set 'isWriterInProgress' flag before it starts modifying
+ // the hashtable and will ckear the flag when it is done. When the flag is cleared, the 'version'
+ // will be increased. We will repeat the reading if a writer is in progress or done with the modification
+ // during the read.
+ //
+ // Our memory model guarantee if we pick up the change in bucket from another processor,
+ // we will see the 'isWriterProgress' flag to be true or 'version' is changed in the reader.
+ //
+ SpinWait spin = new SpinWait();
+ while (true)
+ {
+ // this is volatile read, following memory accesses can not be moved ahead of it.
+ currentversion = _version;
+ b = lbuckets[bucketNumber];
+
+ if (!_isWriterInProgress && (currentversion == _version))
+ break;
+
+ spin.SpinOnce();
+ }
+
+ if (b.key == null)
+ {
+ return null;
+ }
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(b.key, key))
+ return b.val;
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)lbuckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
+ return null;
+ }
+
+ set
+ {
+ Insert(key, value, false);
+ }
+ }
+
+ // Increases the bucket count of this hashtable. This method is called from
+ // the Insert method when the actual load factor of the hashtable reaches
+ // the upper limit specified when the hashtable was constructed. The number
+ // of buckets in the hashtable is increased to the smallest prime number
+ // that is larger than twice the current number of buckets, and the entries
+ // in the hashtable are redistributed into the new buckets using the cached
+ // hashcodes.
+ private void expand()
+ {
+ int rawsize = HashHelpers.ExpandPrime(_buckets.Length);
+ rehash(rawsize);
+ }
+
+ // We occasionally need to rehash the table to clean up the collision bits.
+ private void rehash()
+ {
+ rehash(_buckets.Length);
+ }
+
+ private void UpdateVersion()
+ {
+ // Version might become negative when version is int.MaxValue, but the oddity will be still be correct.
+ // So we don't need to special case this.
+ _version++;
+ }
+
+ private void rehash(int newsize)
+ {
+ // reset occupancy
+ _occupancy = 0;
+
+ // Don't replace any internal state until we've finished adding to the
+ // new bucket[]. This serves two purposes:
+ // 1) Allow concurrent readers to see valid hashtable contents
+ // at all times
+ // 2) Protect against an OutOfMemoryException while allocating this
+ // new bucket[].
+ bucket[] newBuckets = new bucket[newsize];
+
+ // rehash table into new buckets
+ int nb;
+ for (nb = 0; nb < _buckets.Length; nb++)
+ {
+ bucket oldb = _buckets[nb];
+ if ((oldb.key != null) && (oldb.key != _buckets))
+ {
+ int hashcode = oldb.hash_coll & 0x7FFFFFFF;
+ putEntry(newBuckets, oldb.key, oldb.val, hashcode);
+ }
+ }
+
+ // New bucket[] is good to go - replace buckets and other internal state.
+ _isWriterInProgress = true;
+ _buckets = newBuckets;
+ _loadsize = (int)(_loadFactor * newsize);
+ UpdateVersion();
+ _isWriterInProgress = false;
+ // minimum size of hashtable is 3 now and maximum loadFactor is 0.72 now.
+ Debug.Assert(_loadsize < newsize, "Our current implementation means this is not possible.");
+ }
+
+ // Returns an enumerator for this hashtable.
+ // If modifications made to the hashtable while an enumeration is
+ // in progress, the MoveNext and Current methods of the
+ // enumerator will throw an exception.
+ //
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new HashtableEnumerator(this, HashtableEnumerator.DictEntry);
+ }
+
+ // Returns a dictionary enumerator for this hashtable.
+ // If modifications made to the hashtable while an enumeration is
+ // in progress, the MoveNext and Current methods of the
+ // enumerator will throw an exception.
+ //
+ public virtual IDictionaryEnumerator GetEnumerator()
+ {
+ return new HashtableEnumerator(this, HashtableEnumerator.DictEntry);
+ }
+
+ // Internal method to get the hash code for an Object. This will call
+ // GetHashCode() on each object if you haven't provided an IHashCodeProvider
+ // instance. Otherwise, it calls hcp.GetHashCode(obj).
+ protected virtual int GetHash(object key)
+ {
+ if (_keycomparer != null)
+ return _keycomparer.GetHashCode(key);
+ return key.GetHashCode();
+ }
+
+ // Is this Hashtable read-only?
+ public virtual bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsFixedSize
+ {
+ get { return false; }
+ }
+
+ // Is this Hashtable synchronized? See SyncRoot property
+ public virtual bool IsSynchronized
+ {
+ get { return false; }
+ }
+
+ // Internal method to compare two keys. If you have provided an IComparer
+ // instance in the constructor, this method will call comparer.Compare(item, key).
+ // Otherwise, it will call item.Equals(key).
+ //
+ protected virtual bool KeyEquals(object item, object key)
+ {
+ Debug.Assert(key != null, "key can't be null here!");
+ if (object.ReferenceEquals(_buckets, item))
+ {
+ return false;
+ }
+
+ if (object.ReferenceEquals(item, key))
+ return true;
+
+ if (_keycomparer != null)
+ return _keycomparer.Equals(item, key);
+ return item == null ? false : item.Equals(key);
+ }
+
+ // Returns a collection representing the keys of this hashtable. The order
+ // in which the returned collection represents the keys is unspecified, but
+ // it is guaranteed to be buckets = newBuckets; the same order in which a collection returned by
+ // GetValues represents the values of the hashtable.
+ //
+ // The returned collection is live in the sense that any changes
+ // to the hash table are reflected in this collection. It is not
+ // a static copy of all the keys in the hash table.
+ //
+ public virtual ICollection Keys
+ {
+ get
+ {
+ if (_keys == null)
+ _keys = new KeyCollection(this);
+ return _keys;
+ }
+ }
+
+ // Returns a collection representing the values of this hashtable. The
+ // order in which the returned collection represents the values is
+ // unspecified, but it is guaranteed to be the same order in which a
+ // collection returned by GetKeys represents the keys of the
+ // hashtable.
+ //
+ // The returned collection is live in the sense that any changes
+ // to the hash table are reflected in this collection. It is not
+ // a static copy of all the keys in the hash table.
+ //
+ public virtual ICollection Values
+ {
+ get
+ {
+ if (_values == null)
+ _values = new ValueCollection(this);
+ return _values;
+ }
+ }
+
+ // Inserts an entry into this hashtable. This method is called from the Set
+ // and Add methods. If the add parameter is true and the given key already
+ // exists in the hashtable, an exception is thrown.
+ private void Insert(object key, object nvalue, bool add)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ if (_count >= _loadsize)
+ {
+ expand();
+ }
+ else if (_occupancy > _loadsize && _count > 100)
+ {
+ rehash();
+ }
+
+ uint seed;
+ uint incr;
+ // Assume we only have one thread writing concurrently. Modify
+ // buckets to contain new data, as long as we insert in the right order.
+ uint hashcode = InitHash(key, _buckets.Length, out seed, out incr);
+ int ntry = 0;
+ int emptySlotNumber = -1; // We use the empty slot number to cache the first empty slot. We chose to reuse slots
+ // create by remove that have the collision bit set over using up new slots.
+ int bucketNumber = (int)(seed % (uint)_buckets.Length);
+ do
+ {
+ // Set emptySlot number to current bucket if it is the first available bucket that we have seen
+ // that once contained an entry and also has had a collision.
+ // We need to search this entire collision chain because we have to ensure that there are no
+ // duplicate entries in the table.
+ if (emptySlotNumber == -1 && (_buckets[bucketNumber].key == _buckets) && (_buckets[bucketNumber].hash_coll < 0))//(((buckets[bucketNumber].hash_coll & unchecked(0x80000000))!=0)))
+ emptySlotNumber = bucketNumber;
+
+ // Insert the key/value pair into this bucket if this bucket is empty and has never contained an entry
+ // OR
+ // This bucket once contained an entry but there has never been a collision
+ if ((_buckets[bucketNumber].key == null) ||
+ (_buckets[bucketNumber].key == _buckets && ((_buckets[bucketNumber].hash_coll & unchecked(0x80000000)) == 0)))
+ {
+ // If we have found an available bucket that has never had a collision, but we've seen an available
+ // bucket in the past that has the collision bit set, use the previous bucket instead
+ if (emptySlotNumber != -1) // Reuse slot
+ bucketNumber = emptySlotNumber;
+
+ // We pretty much have to insert in this order. Don't set hash
+ // code until the value & key are set appropriately.
+ _isWriterInProgress = true;
+ _buckets[bucketNumber].val = nvalue;
+ _buckets[bucketNumber].key = key;
+ _buckets[bucketNumber].hash_coll |= (int)hashcode;
+ _count++;
+ UpdateVersion();
+ _isWriterInProgress = false;
+
+ return;
+ }
+
+ // The current bucket is in use
+ // OR
+ // it is available, but has had the collision bit set and we have already found an available bucket
+ if (((_buckets[bucketNumber].hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(_buckets[bucketNumber].key, key))
+ {
+ if (add)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_AddingDuplicate__, _buckets[bucketNumber].key, key));
+ }
+ _isWriterInProgress = true;
+ _buckets[bucketNumber].val = nvalue;
+ UpdateVersion();
+ _isWriterInProgress = false;
+
+ return;
+ }
+
+ // The current bucket is full, and we have therefore collided. We need to set the collision bit
+ // unless we have remembered an available slot previously.
+ if (emptySlotNumber == -1)
+ {// We don't need to set the collision bit here since we already have an empty slot
+ if (_buckets[bucketNumber].hash_coll >= 0)
+ {
+ _buckets[bucketNumber].hash_coll |= unchecked((int)0x80000000);
+ _occupancy++;
+ }
+ }
+
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)_buckets.Length);
+ } while (++ntry < _buckets.Length);
+
+ // This code is here if and only if there were no buckets without a collision bit set in the entire table
+ if (emptySlotNumber != -1)
+ {
+ // We pretty much have to insert in this order. Don't set hash
+ // code until the value & key are set appropriately.
+ _isWriterInProgress = true;
+ _buckets[emptySlotNumber].val = nvalue;
+ _buckets[emptySlotNumber].key = key;
+ _buckets[emptySlotNumber].hash_coll |= (int)hashcode;
+ _count++;
+ UpdateVersion();
+ _isWriterInProgress = false;
+
+ return;
+ }
+
+ // If you see this assert, make sure load factor & count are reasonable.
+ // Then verify that our double hash function (h2, described at top of file)
+ // meets the requirements described above. You should never see this assert.
+ Debug.Fail("hash table insert failed! Load factor too high, or our double hashing function is incorrect.");
+ throw new InvalidOperationException(SR.InvalidOperation_HashInsertFailed);
+ }
+
+ private void putEntry(bucket[] newBuckets, object key, object nvalue, int hashcode)
+ {
+ Debug.Assert(hashcode >= 0, "hashcode >= 0"); // make sure collision bit (sign bit) wasn't set.
+
+ uint seed = (uint)hashcode;
+ uint incr = unchecked((uint)(1 + ((seed * HashHelpers.HashPrime) % ((uint)newBuckets.Length - 1))));
+ int bucketNumber = (int)(seed % (uint)newBuckets.Length);
+ do
+ {
+ if ((newBuckets[bucketNumber].key == null) || (newBuckets[bucketNumber].key == _buckets))
+ {
+ newBuckets[bucketNumber].val = nvalue;
+ newBuckets[bucketNumber].key = key;
+ newBuckets[bucketNumber].hash_coll |= hashcode;
+ return;
+ }
+
+ if (newBuckets[bucketNumber].hash_coll >= 0)
+ {
+ newBuckets[bucketNumber].hash_coll |= unchecked((int)0x80000000);
+ _occupancy++;
+ }
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)newBuckets.Length);
+ } while (true);
+ }
+
+ // Removes an entry from this hashtable. If an entry with the specified
+ // key exists in the hashtable, it is removed. An ArgumentException is
+ // thrown if the key is null.
+ //
+ public virtual void Remove(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ Debug.Assert(!_isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
+
+ uint seed;
+ uint incr;
+ // Assuming only one concurrent writer, write directly into buckets.
+ uint hashcode = InitHash(key, _buckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bn = (int)(seed % (uint)_buckets.Length); // bucketNumber
+ do
+ {
+ b = _buckets[bn];
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(b.key, key))
+ {
+ _isWriterInProgress = true;
+ // Clear hash_coll field, then key, then value
+ _buckets[bn].hash_coll &= unchecked((int)0x80000000);
+ if (_buckets[bn].hash_coll != 0)
+ {
+ _buckets[bn].key = _buckets;
+ }
+ else
+ {
+ _buckets[bn].key = null;
+ }
+ _buckets[bn].val = null; // Free object references sooner & simplify ContainsValue.
+ _count--;
+ UpdateVersion();
+ _isWriterInProgress = false;
+ return;
+ }
+ bn = (int)(((long)bn + incr) % (uint)_buckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < _buckets.Length);
+ }
+
+ // Returns the object to synchronize on for this hash table.
+ public virtual object SyncRoot
+ {
+ get
+ {
+ if (_syncRoot == null)
+ {
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Returns the number of associations in this hashtable.
+ //
+ public virtual int Count
+ {
+ get { return _count; }
+ }
+
+ // Returns a thread-safe wrapper for a Hashtable.
+ //
+ public static Hashtable Synchronized(Hashtable table)
+ {
+ if (table == null)
+ throw new ArgumentNullException(nameof(table));
+ return new SyncHashtable(table);
+ }
+
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException(nameof(info));
+ }
+
+ // This is imperfect - it only works well if all other writes are
+ // also using our synchronized wrapper. But it's still a good idea.
+ lock (SyncRoot)
+ {
+ // This method hasn't been fully tweaked to be safe for a concurrent writer.
+ int oldVersion = _version;
+ info.AddValue(LoadFactorName, _loadFactor);
+ info.AddValue(VersionName, _version);
+
+ //
+ // We need to maintain serialization compatibility with Everett and RTM.
+ // If the comparer is null or a compatible comparer, serialize Hashtable
+ // in a format that can be deserialized on Everett and RTM.
+ //
+ // Also, if the Hashtable is using randomized hashing, serialize the old
+ // view of the _keycomparer so perevious frameworks don't see the new types
+#pragma warning disable 618
+ IEqualityComparer keyComparerForSerilization = _keycomparer;
+
+ if (keyComparerForSerilization == null)
+ {
+ info.AddValue(ComparerName, null, typeof(IComparer));
+ info.AddValue(HashCodeProviderName, null, typeof(IHashCodeProvider));
+ }
+ else if (keyComparerForSerilization is CompatibleComparer)
+ {
+ CompatibleComparer c = keyComparerForSerilization as CompatibleComparer;
+ info.AddValue(ComparerName, c.Comparer, typeof(IComparer));
+ info.AddValue(HashCodeProviderName, c.HashCodeProvider, typeof(IHashCodeProvider));
+ }
+ else
+ {
+ info.AddValue(KeyComparerName, keyComparerForSerilization, typeof(IEqualityComparer));
+ }
+#pragma warning restore 618
+
+ info.AddValue(HashSizeName, _buckets.Length); //This is the length of the bucket array.
+ object[] serKeys = new object[_count];
+ object[] serValues = new object[_count];
+ CopyKeys(serKeys, 0);
+ CopyValues(serValues, 0);
+ info.AddValue(KeysName, serKeys, typeof(object[]));
+ info.AddValue(ValuesName, serValues, typeof(object[]));
+
+ // Explicitly check to see if anyone changed the Hashtable while we
+ // were serializing it. That's a race in their code.
+ if (_version != oldVersion)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+ }
+ }
+
+ //
+ // DeserializationEvent Listener
+ //
+ public virtual void OnDeserialization(object sender)
+ {
+ if (_buckets != null)
+ {
+ // Somebody had a dependency on this hashtable and fixed us up before the ObjectManager got to it.
+ return;
+ }
+
+ SerializationInfo siInfo;
+ HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
+
+ if (siInfo == null)
+ {
+ throw new SerializationException(SR.Serialization_InvalidOnDeser);
+ }
+
+ int hashsize = 0;
+ IComparer c = null;
+
+#pragma warning disable 618
+ IHashCodeProvider hcp = null;
+#pragma warning restore 618
+
+ object[] serKeys = null;
+ object[] serValues = null;
+
+ SerializationInfoEnumerator enumerator = siInfo.GetEnumerator();
+
+ while (enumerator.MoveNext())
+ {
+ switch (enumerator.Name)
+ {
+ case LoadFactorName:
+ _loadFactor = siInfo.GetSingle(LoadFactorName);
+ break;
+ case HashSizeName:
+ hashsize = siInfo.GetInt32(HashSizeName);
+ break;
+ case KeyComparerName:
+ _keycomparer = (IEqualityComparer)siInfo.GetValue(KeyComparerName, typeof(IEqualityComparer));
+ break;
+ case ComparerName:
+ c = (IComparer)siInfo.GetValue(ComparerName, typeof(IComparer));
+ break;
+ case HashCodeProviderName:
+#pragma warning disable 618
+ hcp = (IHashCodeProvider)siInfo.GetValue(HashCodeProviderName, typeof(IHashCodeProvider));
+#pragma warning restore 618
+ break;
+ case KeysName:
+ serKeys = (object[])siInfo.GetValue(KeysName, typeof(object[]));
+ break;
+ case ValuesName:
+ serValues = (object[])siInfo.GetValue(ValuesName, typeof(object[]));
+ break;
+ }
+ }
+
+ _loadsize = (int)(_loadFactor * hashsize);
+
+ // V1 object doesn't has _keycomparer field.
+ if ((_keycomparer == null) && ((c != null) || (hcp != null)))
+ {
+ _keycomparer = new CompatibleComparer(hcp, c);
+ }
+
+ _buckets = new bucket[hashsize];
+
+ if (serKeys == null)
+ {
+ throw new SerializationException(SR.Serialization_MissingKeys);
+ }
+ if (serValues == null)
+ {
+ throw new SerializationException(SR.Serialization_MissingValues);
+ }
+ if (serKeys.Length != serValues.Length)
+ {
+ throw new SerializationException(SR.Serialization_KeyValueDifferentSizes);
+ }
+ for (int i = 0; i < serKeys.Length; i++)
+ {
+ if (serKeys[i] == null)
+ {
+ throw new SerializationException(SR.Serialization_NullKey);
+ }
+ Insert(serKeys[i], serValues[i], true);
+ }
+
+ _version = siInfo.GetInt32(VersionName);
+
+ HashHelpers.SerializationInfoTable.Remove(this);
+ }
+
+ // Implements a Collection for the keys of a hashtable. An instance of this
+ // class is created by the GetKeys method of a hashtable.
+ private class KeyCollection : ICollection
+ {
+ private Hashtable _hashtable;
+
+ internal KeyCollection(Hashtable hashtable)
+ {
+ _hashtable = hashtable;
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - arrayIndex < _hashtable._count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+ _hashtable.CopyKeys(array, arrayIndex);
+ }
+
+ public virtual IEnumerator GetEnumerator()
+ {
+ return new HashtableEnumerator(_hashtable, HashtableEnumerator.Keys);
+ }
+
+ public virtual bool IsSynchronized
+ {
+ get { return _hashtable.IsSynchronized; }
+ }
+
+ public virtual object SyncRoot
+ {
+ get { return _hashtable.SyncRoot; }
+ }
+
+ public virtual int Count
+ {
+ get { return _hashtable._count; }
+ }
+ }
+
+ // Implements a Collection for the values of a hashtable. An instance of
+ // this class is created by the GetValues method of a hashtable.
+ private class ValueCollection : ICollection
+ {
+ private Hashtable _hashtable;
+
+ internal ValueCollection(Hashtable hashtable)
+ {
+ _hashtable = hashtable;
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - arrayIndex < _hashtable._count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+ _hashtable.CopyValues(array, arrayIndex);
+ }
+
+ public virtual IEnumerator GetEnumerator()
+ {
+ return new HashtableEnumerator(_hashtable, HashtableEnumerator.Values);
+ }
+
+ public virtual bool IsSynchronized
+ {
+ get { return _hashtable.IsSynchronized; }
+ }
+
+ public virtual object SyncRoot
+ {
+ get { return _hashtable.SyncRoot; }
+ }
+
+ public virtual int Count
+ {
+ get { return _hashtable._count; }
+ }
+ }
+
+ // Synchronized wrapper for hashtable
+ private class SyncHashtable : Hashtable, IEnumerable
+ {
+ protected Hashtable _table;
+
+ internal SyncHashtable(Hashtable table) : base(false)
+ {
+ _table = table;
+ }
+
+ internal SyncHashtable(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public override int Count
+ {
+ get { return _table.Count; }
+ }
+
+ public override bool IsReadOnly
+ {
+ get { return _table.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize
+ {
+ get { return _table.IsFixedSize; }
+ }
+
+ public override bool IsSynchronized
+ {
+ get { return true; }
+ }
+
+ public override object this[object key]
+ {
+ get
+ {
+ return _table[key];
+ }
+ set
+ {
+ lock (_table.SyncRoot)
+ {
+ _table[key] = value;
+ }
+ }
+ }
+
+ public override object SyncRoot
+ {
+ get { return _table.SyncRoot; }
+ }
+
+ public override void Add(object key, object value)
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.Add(key, value);
+ }
+ }
+
+ public override void Clear()
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.Clear();
+ }
+ }
+
+ public override bool Contains(object key)
+ {
+ return _table.Contains(key);
+ }
+
+ public override bool ContainsKey(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ return _table.ContainsKey(key);
+ }
+
+ public override bool ContainsValue(object key)
+ {
+ lock (_table.SyncRoot)
+ {
+ return _table.ContainsValue(key);
+ }
+ }
+
+ public override void CopyTo(Array array, int arrayIndex)
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.CopyTo(array, arrayIndex);
+ }
+ }
+
+ public override object Clone()
+ {
+ lock (_table.SyncRoot)
+ {
+ return Hashtable.Synchronized((Hashtable)_table.Clone());
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _table.GetEnumerator();
+ }
+
+ public override IDictionaryEnumerator GetEnumerator()
+ {
+ return _table.GetEnumerator();
+ }
+
+ public override ICollection Keys
+ {
+ get
+ {
+ lock (_table.SyncRoot)
+ {
+ return _table.Keys;
+ }
+ }
+ }
+
+ public override ICollection Values
+ {
+ get
+ {
+ lock (_table.SyncRoot)
+ {
+ return _table.Values;
+ }
+ }
+ }
+
+ public override void Remove(object key)
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.Remove(key);
+ }
+ }
+
+ public override void OnDeserialization(object sender)
+ {
+ // Does nothing. We have to implement this because our parent HT implements it,
+ // but it doesn't do anything meaningful. The real work will be done when we
+ // call OnDeserialization on our parent table.
+ }
+
+ internal override KeyValuePairs[] ToKeyValuePairsArray()
+ {
+ return _table.ToKeyValuePairsArray();
+ }
+ }
+
+
+ // Implements an enumerator for a hashtable. The enumerator uses the
+ // internal version number of the hashtable to ensure that no modifications
+ // are made to the hashtable while an enumeration is in progress.
+ private class HashtableEnumerator : IDictionaryEnumerator, ICloneable
+ {
+ private Hashtable _hashtable;
+ private int _bucket;
+ private int _version;
+ private bool _current;
+ private int _getObjectRetType; // What should GetObject return?
+ private object _currentKey;
+ private object _currentValue;
+
+ internal const int Keys = 1;
+ internal const int Values = 2;
+ internal const int DictEntry = 3;
+
+ internal HashtableEnumerator(Hashtable hashtable, int getObjRetType)
+ {
+ _hashtable = hashtable;
+ _bucket = hashtable._buckets.Length;
+ _version = hashtable._version;
+ _current = false;
+ _getObjectRetType = getObjRetType;
+ }
+
+ public object Clone() => MemberwiseClone();
+
+ public virtual object Key
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ return _currentKey;
+ }
+ }
+
+ public virtual bool MoveNext()
+ {
+ if (_version != _hashtable._version)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ while (_bucket > 0)
+ {
+ _bucket--;
+ object keyv = _hashtable._buckets[_bucket].key;
+ if ((keyv != null) && (keyv != _hashtable._buckets))
+ {
+ _currentKey = keyv;
+ _currentValue = _hashtable._buckets[_bucket].val;
+ _current = true;
+ return true;
+ }
+ }
+ _current = false;
+ return false;
+ }
+
+ public virtual DictionaryEntry Entry
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ return new DictionaryEntry(_currentKey, _currentValue);
+ }
+ }
+
+
+ public virtual object Current
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ if (_getObjectRetType == Keys)
+ return _currentKey;
+ else if (_getObjectRetType == Values)
+ return _currentValue;
+ else
+ return new DictionaryEntry(_currentKey, _currentValue);
+ }
+ }
+
+ public virtual object Value
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ return _currentValue;
+ }
+ }
+
+ public virtual void Reset()
+ {
+ if (_version != _hashtable._version)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ _current = false;
+ _bucket = _hashtable._buckets.Length;
+ _currentKey = null;
+ _currentValue = null;
+ }
+ }
+
+ // internal debug view class for hashtable
+ internal class HashtableDebugView
+ {
+ private Hashtable _hashtable;
+
+ public HashtableDebugView(Hashtable hashtable)
+ {
+ if (hashtable == null)
+ {
+ throw new ArgumentNullException(nameof(hashtable));
+ }
+
+ _hashtable = hashtable;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public KeyValuePairs[] Items
+ {
+ get
+ {
+ return _hashtable.ToKeyValuePairsArray();
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs b/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs
index f0149020d..65e37c738 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs
@@ -10,7 +10,7 @@ namespace System.Collections
// synchronization methods.
public interface ICollection : IEnumerable
{
- // Interfaces are not serialable
+ // Interfaces are not serializable
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
//
@@ -49,12 +49,12 @@ namespace System.Collections
// or your language's equivalent to the C# lock keyword as mentioned
// above.
//
- // For collections with no publically available underlying store, the
+ // For collections with no publicly available underlying store, the
// expected implementation is to simply return the this pointer. Note
// that the this pointer may not be sufficient for collections that
// wrap other collections; those should return the underlying
// collection's SyncRoot property.
- Object SyncRoot
+ object SyncRoot
{ get; }
// Is this collection synchronized (i.e., thread-safe)? If you want a
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs
index cef91c3ff..38bab78b3 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs
@@ -17,6 +17,6 @@ namespace System.Collections
// value less than zero if x is less than y, zero if x is equal to y, or a
// value greater than zero if x is greater than y.
//
- int Compare(Object x, Object y);
+ int Compare(object x, object y);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs b/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs
index b934c2399..b077c9192 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs
@@ -15,7 +15,7 @@ namespace System.Collections
// Interfaces are not serializable
// The Item property provides methods to read and edit entries
// in the Dictionary.
- Object this[Object key]
+ object this[object key]
{
get;
set;
@@ -35,11 +35,11 @@ namespace System.Collections
// Returns whether this dictionary contains a particular key.
//
- bool Contains(Object key);
+ bool Contains(object key);
// Adds a key-value pair to the dictionary.
//
- void Add(Object key, Object value);
+ void Add(object key, object value);
// Removes all pairs from the dictionary.
void Clear();
@@ -55,6 +55,6 @@ namespace System.Collections
// Removes a particular key from the dictionary.
//
- void Remove(Object key);
+ void Remove(object key);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs b/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs
index 451cf6897..0cf6aaa15 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs
@@ -39,7 +39,7 @@ namespace System.Collections
// GetKey with no intervening calls to GetNext will return
// the same object.
//
- Object Key
+ object Key
{
get;
}
@@ -50,7 +50,7 @@ namespace System.Collections
// to GetValue with no intervening calls to GetNext will
// return the same object.
//
- Object Value
+ object Value
{
get;
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs b/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs
index 2c2c2e4a9..29a6f475b 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs
@@ -25,7 +25,7 @@ namespace System.Collections
// GetCurrent with no intervening calls to MoveNext
// will return the same object.
//
- Object Current
+ object Current
{
get;
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs
index 35513f577..9b5476896 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs
@@ -10,7 +10,7 @@ namespace System.Collections
// that can be consumed by some of the common collections.
public interface IEqualityComparer
{
- bool Equals(Object x, Object y);
- int GetHashCode(Object obj);
+ bool Equals(object x, object y);
+ int GetHashCode(object obj);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs b/src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs
new file mode 100644
index 000000000..7d6c63f9f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs
@@ -0,0 +1,18 @@
+// 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.
+
+namespace System.Collections
+{
+ /// <summary>
+ /// Provides a mechanism for a <see cref="Hashtable"/> user to override the default
+ /// GetHashCode() function on Objects, providing their own hash function.
+ /// </summary>
+ [Obsolete("Please use IEqualityComparer instead.")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public interface IHashCodeProvider
+ {
+ /// <summary>Returns a hash code for the given object.</summary>
+ int GetHashCode(object obj);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IList.cs b/src/System.Private.CoreLib/shared/System/Collections/IList.cs
index 0110eca1f..25d3b1922 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IList.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IList.cs
@@ -12,7 +12,7 @@ namespace System.Collections
public interface IList : ICollection
{
// The Item property provides methods to read and edit entries in the List.
- Object this[int index]
+ object this[int index]
{
get;
set;
@@ -22,10 +22,10 @@ namespace System.Collections
// implementation-dependent, so while ArrayList may always insert
// in the last available location, a SortedList most likely would not.
// The return value is the position the new element was inserted in.
- int Add(Object value);
+ int Add(object value);
// Returns whether the list contains a particular item.
- bool Contains(Object value);
+ bool Contains(object value);
// Removes all items from the list.
void Clear();
@@ -42,16 +42,16 @@ namespace System.Collections
// Returns the index of a particular item, if it is in the list.
// Returns -1 if the item isn't in the list.
- int IndexOf(Object value);
+ int IndexOf(object value);
// Inserts value into the list at position index.
// index must be non-negative and less than or equal to the
// number of elements in the list. If index equals the number
// of items in the list, then value is appended to the end.
- void Insert(int index, Object value);
+ void Insert(int index, object value);
// Removes an item from the list.
- void Remove(Object value);
+ void Remove(object value);
// Removes the item at position index.
void RemoveAt(int index);
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs b/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs
index a5e4834b9..9041e0d5f 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs
@@ -8,6 +8,6 @@ namespace System.Collections
{
public interface IStructuralComparable
{
- Int32 CompareTo(Object other, IComparer comparer);
+ int CompareTo(object other, IComparer comparer);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs b/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs
index 4e61d5e75..1784da58c 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs
@@ -6,7 +6,7 @@ namespace System.Collections
{
public interface IStructuralEquatable
{
- Boolean Equals(Object other, IEqualityComparer comparer);
+ bool Equals(object other, IEqualityComparer comparer);
int GetHashCode(IEqualityComparer comparer);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs b/src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs
new file mode 100644
index 000000000..9ec6365b9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs
@@ -0,0 +1,33 @@
+// 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.
+
+/*============================================================
+**
+** Class: KeyValuePairs
+**
+** Purpose: Defines key/value pairs for displaying items
+** in a collection class under the debugger.
+**
+===========================================================*/
+
+using System.Diagnostics;
+
+namespace System.Collections
+{
+ [DebuggerDisplay("{_value}", Name = "[{_key}]")]
+ internal class KeyValuePairs
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly object _key;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly object _value;
+
+ public KeyValuePairs(object key, object value)
+ {
+ _value = value;
+ _key = key;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs b/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs
index a8b7a187d..6045778ab 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs
@@ -20,24 +20,20 @@ namespace System.Collections
/// This should not be used if performance is important for large numbers of elements.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-#if CORERT
- public
-#else
- internal
-#endif
- class ListDictionaryInternal : IDictionary
+ // Needs to be public to support binary serialization compatibility
+ public class ListDictionaryInternal : IDictionary
{
private DictionaryNode head; // Do not rename (binary serialization)
private int version; // Do not rename (binary serialization)
private int count; // Do not rename (binary serialization)
[NonSerialized]
- private Object _syncRoot;
+ private object _syncRoot;
public ListDictionaryInternal()
{
}
- public Object this[Object key]
+ public object this[object key]
{
get
{
@@ -138,13 +134,13 @@ namespace System.Collections
}
}
- public Object SyncRoot
+ public object SyncRoot
{
get
{
if (_syncRoot == null)
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
@@ -158,7 +154,7 @@ namespace System.Collections
}
}
- public void Add(Object key, Object value)
+ public void Add(object key, object value)
{
if (key == null)
{
@@ -205,7 +201,7 @@ namespace System.Collections
version++;
}
- public bool Contains(Object key)
+ public bool Contains(object key)
{
if (key == null)
{
@@ -252,7 +248,7 @@ namespace System.Collections
return new NodeEnumerator(this);
}
- public void Remove(Object key)
+ public void Remove(object key)
{
if (key == null)
{
@@ -300,7 +296,7 @@ namespace System.Collections
current = null;
}
- public Object Current
+ public object Current
{
get
{
@@ -320,7 +316,7 @@ namespace System.Collections
}
}
- public Object Key
+ public object Key
{
get
{
@@ -332,7 +328,7 @@ namespace System.Collections
}
}
- public Object Value
+ public object Value
{
get
{
@@ -426,7 +422,7 @@ namespace System.Collections
}
}
- Object ICollection.SyncRoot
+ object ICollection.SyncRoot
{
get
{
@@ -457,7 +453,7 @@ namespace System.Collections
current = null;
}
- public Object Current
+ public object Current
{
get
{
@@ -505,8 +501,8 @@ namespace System.Collections
[Serializable]
private class DictionaryNode
{
- public Object key;
- public Object value;
+ public object key;
+ public object value;
public DictionaryNode next;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs
index 1e1b2c795..53272b386 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs
@@ -15,7 +15,7 @@ namespace System.Collections.ObjectModel
{
private IList<T> items; // Do not rename (binary serialization)
[NonSerialized]
- private Object _syncRoot;
+ private object _syncRoot;
public Collection()
{
@@ -195,7 +195,7 @@ namespace System.Collections.ObjectModel
}
else
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
}
return _syncRoot;
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
index dbf88d8b8..3c4eda204 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
@@ -15,7 +15,7 @@ namespace System.Collections.ObjectModel
{
private IList<T> list; // Do not rename (binary serialization)
[NonSerialized]
- private Object _syncRoot;
+ private object _syncRoot;
public ReadOnlyCollection(IList<T> list)
{
@@ -127,7 +127,7 @@ namespace System.Collections.ObjectModel
}
else
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
}
return _syncRoot;
diff --git a/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs b/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs
index 3cdc90729..5f7108a52 100644
--- a/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs
@@ -2,11 +2,8 @@
// 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.ComponentModel;
-using System.Diagnostics;
using System.Globalization;
-using System.Runtime.InteropServices;
+using System.Threading;
namespace System.ComponentModel
{
@@ -23,6 +20,9 @@ namespace System.ComponentModel
/// </devdoc>
private object _value;
+ // Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache
+ static object s_convertFromInvariantString;
+
/// <devdoc>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.DefaultValueAttribute'/> class, converting the
/// specified value to the
@@ -36,7 +36,11 @@ namespace System.ComponentModel
// load an otherwise normal class.
try
{
- if (type.IsSubclassOf(typeof(Enum)))
+ if (TryConvertFromInvariantString(type, value, out object convertedValue))
+ {
+ _value = convertedValue;
+ }
+ else if (type.IsSubclassOf(typeof(Enum)))
{
_value = Enum.Parse(type, value, true);
}
@@ -48,6 +52,28 @@ namespace System.ComponentModel
{
_value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
+
+ return;
+
+ // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string)
+ bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out object conversionResult)
+ {
+ conversionResult = null;
+
+ // lazy init reflection objects
+ if (s_convertFromInvariantString == null)
+ {
+ Type typeDescriptorType = Type.GetType("System.ComponentModel.TypeDescriptor, System.ComponentModel.TypeConverter", throwOnError: false);
+ Volatile.Write(ref s_convertFromInvariantString, typeDescriptorType == null ? new object() : Delegate.CreateDelegate(typeof(Func<Type, string, object>), typeDescriptorType, "ConvertFromInvariantString", ignoreCase: false));
+ }
+
+ if (!(s_convertFromInvariantString is Func<Type, string, object> convertFromInvariantString))
+ return false;
+
+ conversionResult = convertFromInvariantString(typeToConvert, stringValue);
+
+ return true;
+ }
}
catch
{
diff --git a/src/System.Private.CoreLib/shared/System/Convert.Base64.cs b/src/System.Private.CoreLib/shared/System/Convert.Base64.cs
new file mode 100644
index 000000000..7e2aee31b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Convert.Base64.cs
@@ -0,0 +1,217 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System
+{
+ public static partial class Convert
+ {
+ /// <summary>
+ /// Decode the span of UTF-16 encoded text represented as base 64 into binary data.
+ /// If the input is not a multiple of 4, or contains illegal characters, it will decode as much as it can, to the largest possible multiple of 4.
+ /// This invariant allows continuation of the parse with a slower, whitespace-tolerant algorithm.
+ ///
+ /// <param name="utf16">The input span which contains UTF-16 encoded text in base 64 that needs to be decoded.</param>
+ /// <param name="bytes">The output span which contains the result of the operation, i.e. the decoded binary data.</param>
+ /// <param name="consumed">The number of input bytes consumed during the operation. This can be used to slice the input for subsequent calls, if necessary.</param>
+ /// <param name="written">The number of bytes written into the output span. This can be used to slice the output for subsequent calls, if necessary.</param>
+ /// <returns>Returns:
+ /// - true - The entire input span was successfully parsed.
+ /// - false - Only a part of the input span was successfully parsed. Failure causes may include embedded or trailing whitespace,
+ /// other illegal Base64 characters, trailing characters after an encoding pad ('='), an input span whose length is not divisible by 4
+ /// or a destination span that's too small. <paramref name="consumed"/> and <paramref name="written"/> are set so that
+ /// parsing can continue with a slower whitespace-tolerant algorithm.
+ ///
+ /// Note: This is a cut down version of the implementation of Base64.DecodeFromUtf8(), modified the accept UTF16 chars and act as a fast-path
+ /// helper for the Convert routines when the input string contains no whitespace.
+ ///
+ /// </summary>
+ private static bool TryDecodeFromUtf16(ReadOnlySpan<char> utf16, Span<byte> bytes, out int consumed, out int written)
+ {
+ ref char srcChars = ref MemoryMarshal.GetReference(utf16);
+ ref byte destBytes = ref MemoryMarshal.GetReference(bytes);
+
+ int srcLength = utf16.Length & ~0x3; // only decode input up to the closest multiple of 4.
+ int destLength = bytes.Length;
+
+ int sourceIndex = 0;
+ int destIndex = 0;
+
+ if (utf16.Length == 0)
+ goto DoneExit;
+
+ ref sbyte decodingMap = ref s_decodingMap[0];
+
+ // Last bytes could have padding characters, so process them separately and treat them as valid.
+ const int skipLastChunk = 4;
+
+ int maxSrcLength;
+ if (destLength >= (srcLength >> 2) * 3)
+ {
+ maxSrcLength = srcLength - skipLastChunk;
+ }
+ else
+ {
+ // This should never overflow since destLength here is less than int.MaxValue / 4 * 3 (i.e. 1610612733)
+ // Therefore, (destLength / 3) * 4 will always be less than 2147483641
+ maxSrcLength = (destLength / 3) * 4;
+ }
+
+ while (sourceIndex < maxSrcLength)
+ {
+ int result = Decode(ref Unsafe.Add(ref srcChars, sourceIndex), ref decodingMap);
+ if (result < 0)
+ goto InvalidExit;
+ WriteThreeLowOrderBytes(ref Unsafe.Add(ref destBytes, destIndex), result);
+ destIndex += 3;
+ sourceIndex += 4;
+ }
+
+ if (maxSrcLength != srcLength - skipLastChunk)
+ goto InvalidExit;
+
+ // If input is less than 4 bytes, srcLength == sourceIndex == 0
+ // If input is not a multiple of 4, sourceIndex == srcLength != 0
+ if (sourceIndex == srcLength)
+ {
+ goto InvalidExit;
+ }
+
+ int i0 = Unsafe.Add(ref srcChars, srcLength - 4);
+ int i1 = Unsafe.Add(ref srcChars, srcLength - 3);
+ int i2 = Unsafe.Add(ref srcChars, srcLength - 2);
+ int i3 = Unsafe.Add(ref srcChars, srcLength - 1);
+ if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0)
+ goto InvalidExit;
+
+ i0 = Unsafe.Add(ref decodingMap, i0);
+ i1 = Unsafe.Add(ref decodingMap, i1);
+
+ i0 <<= 18;
+ i1 <<= 12;
+
+ i0 |= i1;
+
+ if (i3 != EncodingPad)
+ {
+ i2 = Unsafe.Add(ref decodingMap, i2);
+ i3 = Unsafe.Add(ref decodingMap, i3);
+
+ i2 <<= 6;
+
+ i0 |= i3;
+ i0 |= i2;
+
+ if (i0 < 0)
+ goto InvalidExit;
+ if (destIndex > destLength - 3)
+ goto InvalidExit;
+ WriteThreeLowOrderBytes(ref Unsafe.Add(ref destBytes, destIndex), i0);
+ destIndex += 3;
+ }
+ else if (i2 != EncodingPad)
+ {
+ i2 = Unsafe.Add(ref decodingMap, i2);
+
+ i2 <<= 6;
+
+ i0 |= i2;
+
+ if (i0 < 0)
+ goto InvalidExit;
+ if (destIndex > destLength - 2)
+ goto InvalidExit;
+ Unsafe.Add(ref destBytes, destIndex) = (byte)(i0 >> 16);
+ Unsafe.Add(ref destBytes, destIndex + 1) = (byte)(i0 >> 8);
+ destIndex += 2;
+ }
+ else
+ {
+ if (i0 < 0)
+ goto InvalidExit;
+ if (destIndex > destLength - 1)
+ goto InvalidExit;
+ Unsafe.Add(ref destBytes, destIndex) = (byte)(i0 >> 16);
+ destIndex += 1;
+ }
+
+ sourceIndex += 4;
+
+ if (srcLength != utf16.Length)
+ goto InvalidExit;
+
+ DoneExit:
+ consumed = sourceIndex;
+ written = destIndex;
+ return true;
+
+ InvalidExit:
+ consumed = sourceIndex;
+ written = destIndex;
+ Debug.Assert((consumed % 4) == 0);
+ return false;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int Decode(ref char encodedChars, ref sbyte decodingMap)
+ {
+ int i0 = encodedChars;
+ int i1 = Unsafe.Add(ref encodedChars, 1);
+ int i2 = Unsafe.Add(ref encodedChars, 2);
+ int i3 = Unsafe.Add(ref encodedChars, 3);
+
+ if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0)
+ return -1; // One or more chars falls outside the 00..ff range. This cannot be a valid Base64 character.
+
+ i0 = Unsafe.Add(ref decodingMap, i0);
+ i1 = Unsafe.Add(ref decodingMap, i1);
+ i2 = Unsafe.Add(ref decodingMap, i2);
+ i3 = Unsafe.Add(ref decodingMap, i3);
+
+ i0 <<= 18;
+ i1 <<= 12;
+ i2 <<= 6;
+
+ i0 |= i3;
+ i1 |= i2;
+
+ i0 |= i1;
+ return i0;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteThreeLowOrderBytes(ref byte destination, int value)
+ {
+ destination = (byte)(value >> 16);
+ Unsafe.Add(ref destination, 1) = (byte)(value >> 8);
+ Unsafe.Add(ref destination, 2) = (byte)value;
+ }
+
+ // Pre-computing this table using a custom string(s_characters) and GenerateDecodingMapAndVerify (found in tests)
+ private static readonly sbyte[] s_decodingMap = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, //62 is placed at index 43 (for +), 63 at index 47 (for /)
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, //52-61 are placed at index 48-57 (for 0-9), 64 at index 61 (for =)
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, //0-25 are placed at index 65-90 (for A-Z)
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, //26-51 are placed at index 97-122 (for a-z)
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bytes over 122 ('z') are invalid and cannot be decoded
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Hence, padding the map with 255, which indicates invalid input
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ private const byte EncodingPad = (byte)'='; // '=', for padding
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Convert.cs b/src/System.Private.CoreLib/shared/System/Convert.cs
index 756bf17fc..1c303d248 100644
--- a/src/System.Private.CoreLib/shared/System/Convert.cs
+++ b/src/System.Private.CoreLib/shared/System/Convert.cs
@@ -96,31 +96,31 @@ namespace System
// When passed Value.DBNull, the Value.ToXXX() methods all throw an
// InvalidCastException.
- public static class Convert
+ public static partial class Convert
{
//A typeof operation is fairly expensive (does a system call), so we'll cache these here
//statically. These are exactly lined up with the TypeCode, eg. ConvertType[TypeCode.Int16]
- //will give you the type of an Int16.
+ //will give you the type of an short.
internal static readonly Type[] ConvertTypes = {
typeof(System.Empty),
- typeof(Object),
+ typeof(object),
typeof(System.DBNull),
- typeof(Boolean),
- typeof(Char),
- typeof(SByte),
- typeof(Byte),
- typeof(Int16),
- typeof(UInt16),
- typeof(Int32),
- typeof(UInt32),
- typeof(Int64),
- typeof(UInt64),
- typeof(Single),
- typeof(Double),
- typeof(Decimal),
+ typeof(bool),
+ typeof(char),
+ typeof(sbyte),
+ typeof(byte),
+ typeof(short),
+ typeof(ushort),
+ typeof(int),
+ typeof(uint),
+ typeof(long),
+ typeof(ulong),
+ typeof(float),
+ typeof(double),
+ typeof(decimal),
typeof(DateTime),
- typeof(Object), //TypeCode is discontinuous so we need a placeholder.
- typeof(String)
+ typeof(object), //TypeCode is discontinuous so we need a placeholder.
+ typeof(string)
};
// Need to special case Enum because typecode will be underlying type, e.g. Int32
@@ -132,7 +132,7 @@ namespace System
't','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
'8','9','+','/','=' };
- private const Int32 base64LineBreakPosition = 76;
+ private const int base64LineBreakPosition = 76;
#if DEBUG
private static bool TriggerAsserts = DoAsserts();
@@ -142,7 +142,7 @@ namespace System
Debug.Assert(ConvertTypes.Length == ((int)TypeCode.String + 1), "[Convert.cctor]ConvertTypes.Length == ((int)TypeCode.String + 1)");
Debug.Assert(ConvertTypes[(int)TypeCode.Empty] == typeof(System.Empty),
"[Convert.cctor]ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty)");
- Debug.Assert(ConvertTypes[(int)TypeCode.String] == typeof(String),
+ Debug.Assert(ConvertTypes[(int)TypeCode.String] == typeof(string),
"[Convert.cctor]ConvertTypes[(int)TypeCode.String]==typeof(System.String)");
Debug.Assert(ConvertTypes[(int)TypeCode.Int32] == typeof(int),
"[Convert.cctor]ConvertTypes[(int)TypeCode.Int32]==typeof(int)");
@@ -150,7 +150,7 @@ namespace System
}
#endif
- public static readonly Object DBNull = System.DBNull.Value;
+ public static readonly object DBNull = System.DBNull.Value;
// Returns the type code for the given object. If the argument is null,
// the result is TypeCode.Empty. If the argument is not a value (i.e. if
@@ -189,12 +189,12 @@ namespace System
// object already has the given type code, in which case the object is
// simply returned. Otherwise, the appropriate ToXXX() is invoked on the
// object's implementation of IConvertible.
- public static Object ChangeType(Object value, TypeCode typeCode)
+ public static object ChangeType(object value, TypeCode typeCode)
{
return ChangeType(value, typeCode, CultureInfo.CurrentCulture);
}
- public static Object ChangeType(Object value, TypeCode typeCode, IFormatProvider provider)
+ public static object ChangeType(object value, TypeCode typeCode, IFormatProvider provider)
{
if (value == null && (typeCode == TypeCode.Empty || typeCode == TypeCode.String || typeCode == TypeCode.Object))
{
@@ -208,7 +208,7 @@ namespace System
}
// This line is invalid for things like Enums that return a TypeCode
- // of Int32, but the object can't actually be cast to an Int32.
+ // of int, but the object can't actually be cast to an int.
// if (v.GetTypeCode() == typeCode) return value;
switch (typeCode)
{
@@ -253,7 +253,7 @@ namespace System
}
}
- internal static Object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
+ internal static object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
{
Debug.Assert(value != null, "[Convert.DefaultToType]value!=null");
if (targetType == null)
@@ -297,7 +297,7 @@ namespace System
if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.String]))
return value.ToString(provider);
if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Object]))
- return (Object)value;
+ return (object)value;
// Need to special case Enum because typecode will be underlying type, e.g. Int32
if (ReferenceEquals(targetType, EnumType))
return (Enum)value;
@@ -309,14 +309,14 @@ namespace System
throw new InvalidCastException(string.Format(SR.InvalidCast_FromTo, value.GetType().FullName, targetType.FullName));
}
- public static Object ChangeType(Object value, Type conversionType)
+ public static object ChangeType(object value, Type conversionType)
{
return ChangeType(value, conversionType, CultureInfo.CurrentCulture);
}
- public static Object ChangeType(Object value, Type conversionType, IFormatProvider provider)
+ public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
{
- if (ReferenceEquals(conversionType, null))
+ if (conversionType is null)
{
throw new ArgumentNullException(nameof(conversionType));
}
@@ -371,45 +371,36 @@ namespace System
if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.String]))
return ic.ToString(provider);
if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Object]))
- return (Object)value;
+ return (object)value;
return ic.ToType(conversionType, provider);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowCharOverflowException() { throw new OverflowException(SR.Overflow_Char); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowByteOverflowException() { throw new OverflowException(SR.Overflow_Byte); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowSByteOverflowException() { throw new OverflowException(SR.Overflow_SByte); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInt16OverflowException() { throw new OverflowException(SR.Overflow_Int16); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowUInt16OverflowException() { throw new OverflowException(SR.Overflow_UInt16); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInt32OverflowException() { throw new OverflowException(SR.Overflow_Int32); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowUInt32OverflowException() { throw new OverflowException(SR.Overflow_UInt32); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInt64OverflowException() { throw new OverflowException(SR.Overflow_Int64); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowUInt64OverflowException() { throw new OverflowException(SR.Overflow_UInt64); }
// Conversions to Boolean
- public static bool ToBoolean(Object value)
+ public static bool ToBoolean(object value)
{
return value == null ? false : ((IConvertible)value).ToBoolean(null);
}
- public static bool ToBoolean(Object value, IFormatProvider provider)
+ public static bool ToBoolean(object value, IFormatProvider provider)
{
return value == null ? false : ((IConvertible)value).ToBoolean(provider);
}
@@ -472,18 +463,18 @@ namespace System
return value != 0;
}
- public static bool ToBoolean(String value)
+ public static bool ToBoolean(string value)
{
if (value == null)
return false;
- return Boolean.Parse(value);
+ return bool.Parse(value);
}
- public static bool ToBoolean(String value, IFormatProvider provider)
+ public static bool ToBoolean(string value, IFormatProvider provider)
{
if (value == null)
return false;
- return Boolean.Parse(value);
+ return bool.Parse(value);
}
public static bool ToBoolean(float value)
@@ -558,27 +549,27 @@ namespace System
public static char ToChar(int value)
{
- if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
+ if (value < 0 || value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
[CLSCompliant(false)]
public static char ToChar(uint value)
{
- if (value > Char.MaxValue) ThrowCharOverflowException();
+ if (value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
public static char ToChar(long value)
{
- if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
+ if (value < 0 || value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
[CLSCompliant(false)]
public static char ToChar(ulong value)
{
- if (value > Char.MaxValue) ThrowCharOverflowException();
+ if (value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
@@ -586,12 +577,12 @@ namespace System
// @VariantSwitch
// Remove FormatExceptions;
//
- public static char ToChar(String value)
+ public static char ToChar(string value)
{
return ToChar(value, null);
}
- public static char ToChar(String value, IFormatProvider provider)
+ public static char ToChar(string value, IFormatProvider provider)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
@@ -649,7 +640,7 @@ namespace System
[CLSCompliant(false)]
public static sbyte ToSByte(bool value)
{
- return value ? (sbyte)Boolean.True : (sbyte)Boolean.False;
+ return value ? (sbyte)bool.True : (sbyte)bool.False;
}
[CLSCompliant(false)]
@@ -661,56 +652,56 @@ namespace System
[CLSCompliant(false)]
public static sbyte ToSByte(char value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(byte value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(short value)
{
- if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value < sbyte.MinValue || value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(ushort value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(int value)
{
- if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value < sbyte.MinValue || value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(uint value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(long value)
{
- if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value < sbyte.MinValue || value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(ulong value)
{
- if (value > (ulong)SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > (ulong)sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
@@ -729,21 +720,21 @@ namespace System
[CLSCompliant(false)]
public static sbyte ToSByte(decimal value)
{
- return Decimal.ToSByte(Decimal.Round(value, 0));
+ return decimal.ToSByte(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static sbyte ToSByte(String value)
+ public static sbyte ToSByte(string value)
{
if (value == null)
return 0;
- return SByte.Parse(value, CultureInfo.CurrentCulture);
+ return sbyte.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static sbyte ToSByte(String value, IFormatProvider provider)
+ public static sbyte ToSByte(string value, IFormatProvider provider)
{
- return SByte.Parse(value, NumberStyles.Integer, provider);
+ return sbyte.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -769,7 +760,7 @@ namespace System
public static byte ToByte(bool value)
{
- return value ? (byte)Boolean.True : (byte)Boolean.False;
+ return value ? (byte)bool.True : (byte)bool.False;
}
public static byte ToByte(byte value)
@@ -779,53 +770,53 @@ namespace System
public static byte ToByte(char value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(sbyte value)
{
- if (value < Byte.MinValue) ThrowByteOverflowException();
+ if (value < byte.MinValue) ThrowByteOverflowException();
return (byte)value;
}
public static byte ToByte(short value)
{
- if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value < byte.MinValue || value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(ushort value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
public static byte ToByte(int value)
{
- if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value < byte.MinValue || value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(uint value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
public static byte ToByte(long value)
{
- if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value < byte.MinValue || value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(ulong value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
@@ -841,21 +832,21 @@ namespace System
public static byte ToByte(decimal value)
{
- return Decimal.ToByte(Decimal.Round(value, 0));
+ return decimal.ToByte(decimal.Round(value, 0));
}
- public static byte ToByte(String value)
+ public static byte ToByte(string value)
{
if (value == null)
return 0;
- return Byte.Parse(value, CultureInfo.CurrentCulture);
+ return byte.Parse(value, CultureInfo.CurrentCulture);
}
- public static byte ToByte(String value, IFormatProvider provider)
+ public static byte ToByte(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Byte.Parse(value, NumberStyles.Integer, provider);
+ return byte.Parse(value, NumberStyles.Integer, provider);
}
public static byte ToByte(DateTime value)
@@ -881,12 +872,12 @@ namespace System
public static short ToInt16(bool value)
{
- return value ? (short)Boolean.True : (short)Boolean.False;
+ return value ? (short)bool.True : (short)bool.False;
}
public static short ToInt16(char value)
{
- if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
@@ -904,20 +895,20 @@ namespace System
[CLSCompliant(false)]
public static short ToInt16(ushort value)
{
- if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
public static short ToInt16(int value)
{
- if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value < short.MinValue || value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
[CLSCompliant(false)]
public static short ToInt16(uint value)
{
- if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
@@ -928,14 +919,14 @@ namespace System
public static short ToInt16(long value)
{
- if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value < short.MinValue || value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
[CLSCompliant(false)]
public static short ToInt16(ulong value)
{
- if (value > (ulong)Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > (ulong)short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
@@ -951,21 +942,21 @@ namespace System
public static short ToInt16(decimal value)
{
- return Decimal.ToInt16(Decimal.Round(value, 0));
+ return decimal.ToInt16(decimal.Round(value, 0));
}
- public static short ToInt16(String value)
+ public static short ToInt16(string value)
{
if (value == null)
return 0;
- return Int16.Parse(value, CultureInfo.CurrentCulture);
+ return short.Parse(value, CultureInfo.CurrentCulture);
}
- public static short ToInt16(String value, IFormatProvider provider)
+ public static short ToInt16(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Int16.Parse(value, NumberStyles.Integer, provider);
+ return short.Parse(value, NumberStyles.Integer, provider);
}
public static short ToInt16(DateTime value)
@@ -995,7 +986,7 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(bool value)
{
- return value ? (ushort)Boolean.True : (ushort)Boolean.False;
+ return value ? (ushort)bool.True : (ushort)bool.False;
}
[CLSCompliant(false)]
@@ -1027,7 +1018,7 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(int value)
{
- if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value < 0 || value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
@@ -1040,7 +1031,7 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(uint value)
{
- if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
@@ -1048,14 +1039,14 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(long value)
{
- if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value < 0 || value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
[CLSCompliant(false)]
public static ushort ToUInt16(ulong value)
{
- if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
@@ -1074,23 +1065,23 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(decimal value)
{
- return Decimal.ToUInt16(Decimal.Round(value, 0));
+ return decimal.ToUInt16(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static ushort ToUInt16(String value)
+ public static ushort ToUInt16(string value)
{
if (value == null)
return 0;
- return UInt16.Parse(value, CultureInfo.CurrentCulture);
+ return ushort.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static ushort ToUInt16(String value, IFormatProvider provider)
+ public static ushort ToUInt16(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return UInt16.Parse(value, NumberStyles.Integer, provider);
+ return ushort.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -1117,7 +1108,7 @@ namespace System
public static int ToInt32(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static int ToInt32(char value)
@@ -1150,7 +1141,7 @@ namespace System
[CLSCompliant(false)]
public static int ToInt32(uint value)
{
- if (value > Int32.MaxValue) ThrowInt32OverflowException();
+ if (value > int.MaxValue) ThrowInt32OverflowException();
return (int)value;
}
@@ -1161,14 +1152,14 @@ namespace System
public static int ToInt32(long value)
{
- if (value < Int32.MinValue || value > Int32.MaxValue) ThrowInt32OverflowException();
+ if (value < int.MinValue || value > int.MaxValue) ThrowInt32OverflowException();
return (int)value;
}
[CLSCompliant(false)]
public static int ToInt32(ulong value)
{
- if (value > Int32.MaxValue) ThrowInt32OverflowException();
+ if (value > int.MaxValue) ThrowInt32OverflowException();
return (int)value;
}
@@ -1204,21 +1195,21 @@ namespace System
public static int ToInt32(decimal value)
{
- return Decimal.ToInt32(Decimal.Round(value, 0));
+ return decimal.ToInt32(decimal.Round(value, 0));
}
- public static int ToInt32(String value)
+ public static int ToInt32(string value)
{
if (value == null)
return 0;
- return Int32.Parse(value, CultureInfo.CurrentCulture);
+ return int.Parse(value, CultureInfo.CurrentCulture);
}
- public static int ToInt32(String value, IFormatProvider provider)
+ public static int ToInt32(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Int32.Parse(value, NumberStyles.Integer, provider);
+ return int.Parse(value, NumberStyles.Integer, provider);
}
public static int ToInt32(DateTime value)
@@ -1248,7 +1239,7 @@ namespace System
[CLSCompliant(false)]
public static uint ToUInt32(bool value)
{
- return value ? (uint)Boolean.True : (uint)Boolean.False;
+ return value ? (uint)bool.True : (uint)bool.False;
}
[CLSCompliant(false)]
@@ -1299,14 +1290,14 @@ namespace System
[CLSCompliant(false)]
public static uint ToUInt32(long value)
{
- if (value < 0 || value > UInt32.MaxValue) ThrowUInt32OverflowException();
+ if (value < 0 || value > uint.MaxValue) ThrowUInt32OverflowException();
return (uint)value;
}
[CLSCompliant(false)]
public static uint ToUInt32(ulong value)
{
- if (value > UInt32.MaxValue) ThrowUInt32OverflowException();
+ if (value > uint.MaxValue) ThrowUInt32OverflowException();
return (uint)value;
}
@@ -1332,23 +1323,23 @@ namespace System
[CLSCompliant(false)]
public static uint ToUInt32(decimal value)
{
- return Decimal.ToUInt32(Decimal.Round(value, 0));
+ return decimal.ToUInt32(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static uint ToUInt32(String value)
+ public static uint ToUInt32(string value)
{
if (value == null)
return 0;
- return UInt32.Parse(value, CultureInfo.CurrentCulture);
+ return uint.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static uint ToUInt32(String value, IFormatProvider provider)
+ public static uint ToUInt32(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return UInt32.Parse(value, NumberStyles.Integer, provider);
+ return uint.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -1375,7 +1366,7 @@ namespace System
public static long ToInt64(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static long ToInt64(char value)
@@ -1419,7 +1410,7 @@ namespace System
[CLSCompliant(false)]
public static long ToInt64(ulong value)
{
- if (value > Int64.MaxValue) ThrowInt64OverflowException();
+ if (value > long.MaxValue) ThrowInt64OverflowException();
return (long)value;
}
@@ -1441,21 +1432,21 @@ namespace System
public static long ToInt64(decimal value)
{
- return Decimal.ToInt64(Decimal.Round(value, 0));
+ return decimal.ToInt64(decimal.Round(value, 0));
}
public static long ToInt64(string value)
{
if (value == null)
return 0;
- return Int64.Parse(value, CultureInfo.CurrentCulture);
+ return long.Parse(value, CultureInfo.CurrentCulture);
}
- public static long ToInt64(String value, IFormatProvider provider)
+ public static long ToInt64(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Int64.Parse(value, NumberStyles.Integer, provider);
+ return long.Parse(value, NumberStyles.Integer, provider);
}
public static long ToInt64(DateTime value)
@@ -1483,7 +1474,7 @@ namespace System
[CLSCompliant(false)]
public static ulong ToUInt64(bool value)
{
- return value ? (ulong)Boolean.True : (ulong)Boolean.False;
+ return value ? (ulong)bool.True : (ulong)bool.False;
}
[CLSCompliant(false)]
@@ -1540,7 +1531,7 @@ namespace System
}
[CLSCompliant(false)]
- public static ulong ToUInt64(UInt64 value)
+ public static ulong ToUInt64(ulong value)
{
return value;
}
@@ -1560,23 +1551,23 @@ namespace System
[CLSCompliant(false)]
public static ulong ToUInt64(decimal value)
{
- return Decimal.ToUInt64(Decimal.Round(value, 0));
+ return decimal.ToUInt64(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static ulong ToUInt64(String value)
+ public static ulong ToUInt64(string value)
{
if (value == null)
return 0;
- return UInt64.Parse(value, CultureInfo.CurrentCulture);
+ return ulong.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static ulong ToUInt64(String value, IFormatProvider provider)
+ public static ulong ToUInt64(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return UInt64.Parse(value, NumberStyles.Integer, provider);
+ return ulong.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -1664,24 +1655,24 @@ namespace System
return (float)value;
}
- public static float ToSingle(String value)
+ public static float ToSingle(string value)
{
if (value == null)
return 0;
- return Single.Parse(value, CultureInfo.CurrentCulture);
+ return float.Parse(value, CultureInfo.CurrentCulture);
}
- public static float ToSingle(String value, IFormatProvider provider)
+ public static float ToSingle(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Single.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
+ return float.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
}
public static float ToSingle(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static float ToSingle(DateTime value)
@@ -1769,23 +1760,23 @@ namespace System
return (double)value;
}
- public static double ToDouble(String value)
+ public static double ToDouble(string value)
{
if (value == null)
return 0;
- return Double.Parse(value, CultureInfo.CurrentCulture);
+ return double.Parse(value, CultureInfo.CurrentCulture);
}
- public static double ToDouble(String value, IFormatProvider provider)
+ public static double ToDouble(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
+ return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
}
public static double ToDouble(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static double ToDouble(DateTime value)
@@ -1867,18 +1858,18 @@ namespace System
return (decimal)value;
}
- public static decimal ToDecimal(String value)
+ public static decimal ToDecimal(string value)
{
if (value == null)
return 0m;
- return Decimal.Parse(value, CultureInfo.CurrentCulture);
+ return decimal.Parse(value, CultureInfo.CurrentCulture);
}
- public static Decimal ToDecimal(String value, IFormatProvider provider)
+ public static decimal ToDecimal(string value, IFormatProvider provider)
{
if (value == null)
return 0m;
- return Decimal.Parse(value, NumberStyles.Number, provider);
+ return decimal.Parse(value, NumberStyles.Number, provider);
}
public static decimal ToDecimal(decimal value)
@@ -1888,7 +1879,7 @@ namespace System
public static decimal ToDecimal(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static decimal ToDecimal(DateTime value)
@@ -1916,14 +1907,14 @@ namespace System
return value == null ? DateTime.MinValue : ((IConvertible)value).ToDateTime(provider);
}
- public static DateTime ToDateTime(String value)
+ public static DateTime ToDateTime(string value)
{
if (value == null)
return new DateTime(0);
return DateTime.Parse(value, CultureInfo.CurrentCulture);
}
- public static DateTime ToDateTime(String value, IFormatProvider provider)
+ public static DateTime ToDateTime(string value, IFormatProvider provider)
{
if (value == null)
return new DateTime(0);
@@ -2004,12 +1995,12 @@ namespace System
// Conversions to String
- public static string ToString(Object value)
+ public static string ToString(object value)
{
return ToString(value, null);
}
- public static string ToString(Object value, IFormatProvider provider)
+ public static string ToString(object value, IFormatProvider provider)
{
IConvertible ic = value as IConvertible;
if (ic != null)
@@ -2017,7 +2008,7 @@ namespace System
IFormattable formattable = value as IFormattable;
if (formattable != null)
return formattable.ToString(null, provider);
- return value == null ? String.Empty : value.ToString();
+ return value == null ? string.Empty : value.ToString();
}
public static string ToString(bool value)
@@ -2032,7 +2023,7 @@ namespace System
public static string ToString(char value)
{
- return Char.ToString(value);
+ return char.ToString(value);
}
public static string ToString(char value, IFormatProvider provider)
@@ -2153,7 +2144,7 @@ namespace System
return value.ToString(CultureInfo.CurrentCulture);
}
- public static string ToString(Decimal value, IFormatProvider provider)
+ public static string ToString(decimal value, IFormatProvider provider)
{
return value.ToString(provider);
}
@@ -2168,12 +2159,12 @@ namespace System
return value.ToString(provider);
}
- public static String ToString(String value)
+ public static string ToString(string value)
{
return value;
}
- public static String ToString(String value, IFormatProvider provider)
+ public static string ToString(string value, IFormatProvider provider)
{
return value; // avoid the null check
}
@@ -2186,7 +2177,7 @@ namespace System
// be 2, 8, 10, or 16. If base is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static byte ToByte(String value, int fromBase)
+ public static byte ToByte(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2199,7 +2190,7 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
- if (r < Byte.MinValue || r > Byte.MaxValue)
+ if (r < byte.MinValue || r > byte.MaxValue)
ThrowByteOverflowException();
return (byte)r;
}
@@ -2209,7 +2200,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static sbyte ToSByte(String value, int fromBase)
+ public static sbyte ToSByte(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2222,10 +2213,10 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsI1);
- if (fromBase != 10 && r <= Byte.MaxValue)
+ if (fromBase != 10 && r <= byte.MaxValue)
return (sbyte)r;
- if (r < SByte.MinValue || r > SByte.MaxValue)
+ if (r < sbyte.MinValue || r > sbyte.MaxValue)
ThrowSByteOverflowException();
return (sbyte)r;
}
@@ -2234,7 +2225,7 @@ namespace System
// be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static short ToInt16(String value, int fromBase)
+ public static short ToInt16(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2247,10 +2238,10 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsI2);
- if (fromBase != 10 && r <= UInt16.MaxValue)
+ if (fromBase != 10 && r <= ushort.MaxValue)
return (short)r;
- if (r < Int16.MinValue || r > Int16.MaxValue)
+ if (r < short.MinValue || r > short.MaxValue)
ThrowInt16OverflowException();
return (short)r;
}
@@ -2260,7 +2251,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static ushort ToUInt16(String value, int fromBase)
+ public static ushort ToUInt16(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2273,7 +2264,7 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
- if (r < UInt16.MinValue || r > UInt16.MaxValue)
+ if (r < ushort.MinValue || r > ushort.MaxValue)
ThrowUInt16OverflowException();
return (ushort)r;
}
@@ -2282,7 +2273,7 @@ namespace System
// be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static int ToInt32(String value, int fromBase)
+ public static int ToInt32(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2298,7 +2289,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static uint ToUInt32(String value, int fromBase)
+ public static uint ToUInt32(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2313,7 +2304,7 @@ namespace System
// be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static long ToInt64(String value, int fromBase)
+ public static long ToInt64(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2329,7 +2320,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static ulong ToUInt64(String value, int fromBase)
+ public static ulong ToUInt64(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2341,7 +2332,7 @@ namespace System
}
// Convert the byte value to a string in base fromBase
- public static String ToString(byte value, int toBase)
+ public static string ToString(byte value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2351,7 +2342,7 @@ namespace System
}
// Convert the Int16 value to a string in base fromBase
- public static String ToString(short value, int toBase)
+ public static string ToString(short value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2361,7 +2352,7 @@ namespace System
}
// Convert the Int32 value to a string in base toBase
- public static String ToString(int value, int toBase)
+ public static string ToString(int value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2371,7 +2362,7 @@ namespace System
}
// Convert the Int64 value to a string in base toBase
- public static String ToString(long value, int toBase)
+ public static string ToString(long value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2380,7 +2371,7 @@ namespace System
return ParseNumbers.LongToString(value, toBase, -1, ' ', 0);
}
- public static String ToBase64String(byte[] inArray)
+ public static string ToBase64String(byte[] inArray)
{
if (inArray == null)
{
@@ -2389,7 +2380,7 @@ namespace System
return ToBase64String(new ReadOnlySpan<byte>(inArray), Base64FormattingOptions.None);
}
- public static String ToBase64String(byte[] inArray, Base64FormattingOptions options)
+ public static string ToBase64String(byte[] inArray, Base64FormattingOptions options)
{
if (inArray == null)
{
@@ -2398,12 +2389,12 @@ namespace System
return ToBase64String(new ReadOnlySpan<byte>(inArray), options);
}
- public static String ToBase64String(byte[] inArray, int offset, int length)
+ public static string ToBase64String(byte[] inArray, int offset, int length)
{
return ToBase64String(inArray, offset, length, Base64FormattingOptions.None);
}
- public static String ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options)
+ public static string ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options)
{
if (inArray == null)
throw new ArgumentNullException(nameof(inArray));
@@ -2629,7 +2620,7 @@ namespace System
/// </summary>
/// <param name="s">The string to convert</param>
/// <returns>The array of bytes represented by the specified Base64 string.</returns>
- public static Byte[] FromBase64String(String s)
+ public static byte[] FromBase64String(string s)
{
// "s" is an unfortunate parameter name, but we need to keep it for backward compat.
@@ -2639,7 +2630,7 @@ namespace System
unsafe
{
- fixed (Char* sPtr = s)
+ fixed (char* sPtr = s)
{
return FromBase64CharPtr(sPtr, s.Length);
}
@@ -2656,44 +2647,124 @@ namespace System
return TryFromBase64Chars(s.AsSpan(), bytes, out bytesWritten);
}
- public static unsafe bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
+ public static bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
{
- if (chars.Length == 0)
- {
- bytesWritten = 0;
- return true;
- }
+ // This is actually local to one of the nested blocks but is being declared at the top as we don't want multiple stackallocs
+ // for each iteraton of the loop.
+ Span<char> tempBuffer = stackalloc char[4]; // Note: The tempBuffer size could be made larger than 4 but the size must be a multiple of 4.
- // We need to get rid of any trailing white spaces.
- // Otherwise we would be rejecting input such as "abc= ":
- while (chars.Length > 0)
+ bytesWritten = 0;
+
+ while (chars.Length != 0)
{
- char lastChar = chars[chars.Length - 1];
- if (lastChar != ' ' && lastChar != '\n' && lastChar != '\r' && lastChar != '\t')
+ // Attempt to decode a segment that doesn't contain whitespace.
+ bool complete = TryDecodeFromUtf16(chars, bytes, out int consumedInThisIteration, out int bytesWrittenInThisIteration);
+ bytesWritten += bytesWrittenInThisIteration;
+ if (complete)
+ return true;
+
+ chars = chars.Slice(consumedInThisIteration);
+ bytes = bytes.Slice(bytesWrittenInThisIteration);
+
+ Debug.Assert(chars.Length != 0); // If TryDecodeFromUtf16() consumed the entire buffer, it could not have returned false.
+ if (chars[0].IsSpace())
{
- break;
- }
- chars = chars.Slice(0, chars.Length - 1);
- }
+ // If we got here, the very first character not consumed was a whitespace. We can skip past any consecutive whitespace, then continue decoding.
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- {
- int resultLength = FromBase64_ComputeResultLength(charsPtr, chars.Length);
- Debug.Assert(resultLength >= 0);
- if (resultLength > bytes.Length)
+ int indexOfFirstNonSpace = 1;
+ for (; ; )
+ {
+ if (indexOfFirstNonSpace == chars.Length)
+ break;
+ if (!chars[indexOfFirstNonSpace].IsSpace())
+ break;
+ indexOfFirstNonSpace++;
+ }
+
+ chars = chars.Slice(indexOfFirstNonSpace);
+
+ if ((bytesWrittenInThisIteration % 3) != 0 && chars.Length != 0)
+ {
+ // If we got here, the last successfully decoded block encountered an end-marker, yet we have trailing non-whitespace characters.
+ // That is not allowed.
+ bytesWritten = default;
+ return false;
+ }
+
+ // We now loop again to decode the next run of non-space characters.
+ }
+ else
{
- bytesWritten = 0;
- return false;
+ Debug.Assert(chars.Length != 0 && !chars[0].IsSpace());
+
+ // If we got here, it is possible that there is whitespace that occurred in the middle of a 4-byte chunk. That is, we still have
+ // up to three Base64 characters that were left undecoded by the fast-path helper because they didn't form a complete 4-byte chunk.
+ // This is hopefully the rare case (multiline-formatted base64 message with a non-space character width that's not a multiple of 4.)
+ // We'll filter out whitespace and copy the remaining characters into a temporary buffer.
+ CopyToTempBufferWithoutWhiteSpace(chars, tempBuffer, out int consumedFromChars, out int charsWritten);
+ if ((charsWritten & 0x3) != 0)
+ {
+ // Even after stripping out whitespace, the number of characters is not divisible by 4. This cannot be a legal Base64 string.
+ bytesWritten = default;
+ return false;
+ }
+
+ tempBuffer = tempBuffer.Slice(0, charsWritten);
+ if (!TryDecodeFromUtf16(tempBuffer, bytes, out int consumedFromTempBuffer, out int bytesWrittenFromTempBuffer))
+ {
+ bytesWritten = default;
+ return false;
+ }
+ bytesWritten += bytesWrittenFromTempBuffer;
+ chars = chars.Slice(consumedFromChars);
+ bytes = bytes.Slice(bytesWrittenFromTempBuffer);
+
+ if ((bytesWrittenFromTempBuffer % 3) != 0)
+ {
+ // If we got here, this decode contained one or more padding characters ('='). We can accept trailing whitespace after this
+ // but nothing else.
+ for (int i = 0; i < chars.Length; i++)
+ {
+ if (!chars[i].IsSpace())
+ {
+ bytesWritten = default;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // We now loop again to decode the next run of non-space characters.
}
+ }
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ return true;
+ }
+
+ private static void CopyToTempBufferWithoutWhiteSpace(ReadOnlySpan<char> chars, Span<char> tempBuffer, out int consumed, out int charsWritten)
+ {
+ Debug.Assert(tempBuffer.Length != 0); // We only bound-check after writing a character to the tempBuffer.
+
+ charsWritten = 0;
+ for (int i = 0; i < chars.Length; i++)
+ {
+ char c = chars[i];
+ if (!c.IsSpace())
{
- bytesWritten = FromBase64_Decode(charsPtr, chars.Length, bytesPtr, bytes.Length);
- return true;
+ tempBuffer[charsWritten++] = c;
+ if (charsWritten == tempBuffer.Length)
+ {
+ consumed = i + 1;
+ return;
+ }
}
}
+ consumed = chars.Length;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool IsSpace(this char c) => c == ' ' || c == '\t' || c == '\r' || c == '\n';
+
/// <summary>
/// Converts the specified range of a Char array, which encodes binary data as Base64 digits, to the equivalent byte array.
/// </summary>
@@ -2701,7 +2772,7 @@ namespace System
/// <param name="offset">A position within the input array.</param>
/// <param name="length">Number of element to convert.</param>
/// <returns>The array of bytes represented by the specified Base64 encoding characters.</returns>
- public static Byte[] FromBase64CharArray(Char[] inArray, Int32 offset, Int32 length)
+ public static byte[] FromBase64CharArray(char[] inArray, int offset, int length)
{
if (inArray == null)
throw new ArgumentNullException(nameof(inArray));
@@ -2723,15 +2794,13 @@ namespace System
unsafe
{
- fixed (Char* inArrayPtr = &inArray[0])
+ fixed (char* inArrayPtr = &inArray[0])
{
return FromBase64CharPtr(inArrayPtr + offset, length);
}
}
}
-
-
/// <summary>
/// Convert Base64 encoding characters to bytes:
/// - Compute result length exactly by actually walking the input;
@@ -2741,7 +2810,7 @@ namespace System
/// <param name="inputPtr">Pointer to the first input char</param>
/// <param name="inputLength">Number of input chars</param>
/// <returns></returns>
- private static unsafe Byte[] FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
+ private static unsafe byte[] FromBase64CharPtr(char* inputPtr, int inputLength)
{
// The validity of parameters much be checked by callers, thus we are Critical here.
@@ -2751,14 +2820,14 @@ namespace System
// Otherwise we would be rejecting input such as "abc= ":
while (inputLength > 0)
{
- Int32 lastChar = inputPtr[inputLength - 1];
- if (lastChar != (Int32)' ' && lastChar != (Int32)'\n' && lastChar != (Int32)'\r' && lastChar != (Int32)'\t')
+ int lastChar = inputPtr[inputLength - 1];
+ if (lastChar != (int)' ' && lastChar != (int)'\n' && lastChar != (int)'\r' && lastChar != (int)'\t')
break;
inputLength--;
}
// Compute the output length:
- Int32 resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength);
+ int resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength);
Debug.Assert(0 <= resultLength);
@@ -2766,14 +2835,13 @@ namespace System
// It may either simply write no bytes (e.g. input = " ") or throw (e.g. input = "ab").
// Create result byte blob:
- Byte[] decodedBytes = new Byte[resultLength];
+ byte[] decodedBytes = new byte[resultLength];
// Convert Base64 chars into bytes:
- Int32 actualResultLength;
- fixed (Byte* decodedBytesPtr = decodedBytes)
- actualResultLength = FromBase64_Decode(inputPtr, inputLength, decodedBytesPtr, resultLength);
+ if (!TryFromBase64Chars(new ReadOnlySpan<char>(inputPtr, inputLength), decodedBytes, out int _))
+ throw new FormatException(SR.Format_BadBase64Char);
- // Note that actualResultLength can differ from resultLength if the caller is modifying the array
+ // Note that the number of bytes written can differ from resultLength if the caller is modifying the array
// as it is being converted. Silently ignore the failure.
// Consider throwing exception in an non in-place release.
@@ -2781,218 +2849,25 @@ namespace System
return decodedBytes;
}
-
- /// <summary>
- /// Decode characters representing a Base64 encoding into bytes:
- /// Walk the input. Every time 4 chars are read, convert them to the 3 corresponding output bytes.
- /// This method is a bit lengthy on purpose. We are trying to avoid jumps to helpers in the loop
- /// to aid performance.
- /// </summary>
- /// <param name="inputPtr">Pointer to first input char</param>
- /// <param name="inputLength">Number of input chars</param>
- /// <param name="destPtr">Pointer to location for the first result byte</param>
- /// <param name="destLength">Max length of the preallocated result buffer</param>
- /// <returns>If the result buffer was not large enough to write all result bytes, return -1;
- /// Otherwise return the number of result bytes actually produced.</returns>
- private static unsafe Int32 FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
- {
- // You may find this method weird to look at. It's written for performance, not aesthetics.
- // You will find unrolled loops label jumps and bit manipulations.
-
- const UInt32 intA = (UInt32)'A';
- const UInt32 inta = (UInt32)'a';
- const UInt32 int0 = (UInt32)'0';
- const UInt32 intEq = (UInt32)'=';
- const UInt32 intPlus = (UInt32)'+';
- const UInt32 intSlash = (UInt32)'/';
- const UInt32 intSpace = (UInt32)' ';
- const UInt32 intTab = (UInt32)'\t';
- const UInt32 intNLn = (UInt32)'\n';
- const UInt32 intCRt = (UInt32)'\r';
- const UInt32 intAtoZ = (UInt32)('Z' - 'A'); // = ('z' - 'a')
- const UInt32 int0to9 = (UInt32)('9' - '0');
-
- Char* inputPtr = startInputPtr;
- Byte* destPtr = startDestPtr;
-
- // Pointers to the end of input and output:
- Char* endInputPtr = inputPtr + inputLength;
- Byte* endDestPtr = destPtr + destLength;
-
- // Current char code/value:
- UInt32 currCode;
-
- // This 4-byte integer will contain the 4 codes of the current 4-char group.
- // Eeach char codes for 6 bits = 24 bits.
- // The remaining byte will be FF, we use it as a marker when 4 chars have been processed.
- UInt32 currBlockCodes = 0x000000FFu;
-
- unchecked
- {
- while (true)
- {
- // break when done:
- if (inputPtr >= endInputPtr)
- goto _AllInputConsumed;
-
- // Get current char:
- currCode = (UInt32)(*inputPtr);
- inputPtr++;
-
- // Determine current char code:
-
- if (currCode - intA <= intAtoZ)
- currCode -= intA;
-
- else if (currCode - inta <= intAtoZ)
- currCode -= (inta - 26u);
-
- else if (currCode - int0 <= int0to9)
- currCode -= (int0 - 52u);
-
- else
- {
- // Use the slower switch for less common cases:
- switch (currCode)
- {
- // Significant chars:
- case intPlus:
- currCode = 62u;
- break;
-
- case intSlash:
- currCode = 63u;
- break;
-
- // Legal no-value chars (we ignore these):
- case intCRt:
- case intNLn:
- case intSpace:
- case intTab:
- continue;
-
- // The equality char is only legal at the end of the input.
- // Jump after the loop to make it easier for the JIT register predictor to do a good job for the loop itself:
- case intEq:
- goto _EqualityCharEncountered;
-
- // Other chars are illegal:
- default:
- throw new FormatException(SR.Format_BadBase64Char);
- }
- }
-
- // Ok, we got the code. Save it:
- currBlockCodes = (currBlockCodes << 6) | currCode;
-
- // Last bit in currBlockCodes will be on after in shifted right 4 times:
- if ((currBlockCodes & 0x80000000u) != 0u)
- {
- if ((Int32)(endDestPtr - destPtr) < 3)
- return -1;
-
- *(destPtr) = (Byte)(currBlockCodes >> 16);
- *(destPtr + 1) = (Byte)(currBlockCodes >> 8);
- *(destPtr + 2) = (Byte)(currBlockCodes);
- destPtr += 3;
-
- currBlockCodes = 0x000000FFu;
- }
- }
- } // unchecked while
-
- // 'd be nice to have an assert that we never get here, but CS0162: Unreachable code detected.
- // Debug.Fail("We only leave the above loop by jumping; should never get here.");
-
- // We jump here out of the loop if we hit an '=':
- _EqualityCharEncountered:
-
- Debug.Assert(currCode == intEq);
-
- // Recall that inputPtr is now one position past where '=' was read.
- // '=' can only be at the last input pos:
- if (inputPtr == endInputPtr)
- {
- // Code is zero for trailing '=':
- currBlockCodes <<= 6;
-
- // The '=' did not complete a 4-group. The input must be bad:
- if ((currBlockCodes & 0x80000000u) == 0u)
- throw new FormatException(SR.Format_BadBase64CharArrayLength);
-
- if ((int)(endDestPtr - destPtr) < 2) // Autch! We underestimated the output length!
- return -1;
-
- // We are good, store bytes form this past group. We had a single "=", so we take two bytes:
- *(destPtr++) = (Byte)(currBlockCodes >> 16);
- *(destPtr++) = (Byte)(currBlockCodes >> 8);
-
- currBlockCodes = 0x000000FFu;
- }
- else
- { // '=' can also be at the pre-last position iff the last is also a '=' excluding the white spaces:
- // We need to get rid of any intermediate white spaces.
- // Otherwise we would be rejecting input such as "abc= =":
- while (inputPtr < (endInputPtr - 1))
- {
- Int32 lastChar = *(inputPtr);
- if (lastChar != (Int32)' ' && lastChar != (Int32)'\n' && lastChar != (Int32)'\r' && lastChar != (Int32)'\t')
- break;
- inputPtr++;
- }
-
- if (inputPtr == (endInputPtr - 1) && *(inputPtr) == '=')
- {
- // Code is zero for each of the two '=':
- currBlockCodes <<= 12;
-
- // The '=' did not complete a 4-group. The input must be bad:
- if ((currBlockCodes & 0x80000000u) == 0u)
- throw new FormatException(SR.Format_BadBase64CharArrayLength);
-
- if ((Int32)(endDestPtr - destPtr) < 1) // Autch! We underestimated the output length!
- return -1;
-
- // We are good, store bytes form this past group. We had a "==", so we take only one byte:
- *(destPtr++) = (Byte)(currBlockCodes >> 16);
-
- currBlockCodes = 0x000000FFu;
- }
- else // '=' is not ok at places other than the end:
- throw new FormatException(SR.Format_BadBase64Char);
- }
-
- // We get here either from above or by jumping out of the loop:
- _AllInputConsumed:
-
- // The last block of chars has less than 4 items
- if (currBlockCodes != 0x000000FFu)
- throw new FormatException(SR.Format_BadBase64CharArrayLength);
-
- // Return how many bytes were actually recovered:
- return (Int32)(destPtr - startDestPtr);
- } // Int32 FromBase64_Decode(...)
-
-
/// <summary>
/// Compute the number of bytes encoded in the specified Base 64 char array:
/// Walk the entire input counting white spaces and padding chars, then compute result length
/// based on 3 bytes per 4 chars.
/// </summary>
- private static unsafe Int32 FromBase64_ComputeResultLength(Char* inputPtr, Int32 inputLength)
+ private static unsafe int FromBase64_ComputeResultLength(char* inputPtr, int inputLength)
{
- const UInt32 intEq = (UInt32)'=';
- const UInt32 intSpace = (UInt32)' ';
+ const uint intEq = (uint)'=';
+ const uint intSpace = (uint)' ';
Debug.Assert(0 <= inputLength);
- Char* inputEndPtr = inputPtr + inputLength;
- Int32 usefulInputLength = inputLength;
- Int32 padding = 0;
+ char* inputEndPtr = inputPtr + inputLength;
+ int usefulInputLength = inputLength;
+ int padding = 0;
while (inputPtr < inputEndPtr)
{
- UInt32 c = (UInt32)(*inputPtr);
+ uint c = (uint)(*inputPtr);
inputPtr++;
// We want to be as fast as possible and filter out spaces with as few comparisons as possible.
diff --git a/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs b/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
index bab6a92bf..0112c81ab 100644
--- a/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
+++ b/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
@@ -17,25 +17,21 @@
**
============================================================*/
-using System;
-using System.Text;
using System.Collections;
using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Runtime.Versioning;
namespace System
{
[Obsolete("System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead.")]
- internal partial class CurrentSystemTimeZone : TimeZone
+ internal class CurrentSystemTimeZone : TimeZone
{
// Standard offset in ticks to the Universal time if
// no daylight saving is in used.
// E.g. the offset for PST (Pacific Standard time) should be -8 * 60 * 60 * 1000 * 10000.
// (1 millisecond = 10000 ticks)
private long m_ticksOffset;
- private String m_standardName;
- private String m_daylightName;
+ private string m_standardName;
+ private string m_daylightName;
internal CurrentSystemTimeZone()
{
@@ -46,7 +42,7 @@ namespace System
m_daylightName = local.DaylightName;
}
- public override String StandardName
+ public override string StandardName
{
get
{
@@ -54,7 +50,7 @@ namespace System
}
}
- public override String DaylightName
+ public override string DaylightName
{
get
{
@@ -62,7 +58,7 @@ namespace System
}
}
- internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst)
+ internal long GetUtcOffsetFromUniversalTime(DateTime time, ref bool isAmbiguousLocalDst)
{
// Get the daylight changes for the year of the specified time.
TimeSpan offset = new TimeSpan(m_ticksOffset);
@@ -93,7 +89,7 @@ namespace System
ambiguousEnd = startTime - daylightTime.Delta;
}
- Boolean isDst = false;
+ bool isDst = false;
if (startTime > endTime)
{
// In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
@@ -126,8 +122,8 @@ namespace System
{
return time;
}
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ bool isAmbiguousLocalDst = false;
+ long offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
long tick = time.Ticks + offset;
if (tick > DateTime.MaxTicks)
{
@@ -193,5 +189,29 @@ namespace System
return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);
}
}
+
+ private DaylightTime GetCachedDaylightChanges(int year)
+ {
+ object objYear = (object)year;
+
+ if (!m_CachedDaylightChanges.Contains(objYear))
+ {
+ DaylightTime currentDaylightChanges = CreateDaylightChanges(year);
+ lock (m_CachedDaylightChanges)
+ {
+ if (!m_CachedDaylightChanges.Contains(objYear))
+ {
+ m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
+ }
+ }
+ }
+
+ return (DaylightTime)m_CachedDaylightChanges[objYear];
+ }
+
+ // The per-year information is cached in in this instance value. As a result it can
+ // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
+ private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
+
} // class CurrentSystemTimeZone
}
diff --git a/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs b/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs
index 2a245b6ef..940407fc5 100644
--- a/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs
+++ b/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs
@@ -23,13 +23,13 @@ namespace System
HResult = HResults.COR_E_DATAMISALIGNED;
}
- public DataMisalignedException(String message)
+ public DataMisalignedException(string message)
: base(message)
{
HResult = HResults.COR_E_DATAMISALIGNED;
}
- public DataMisalignedException(String message, Exception innerException)
+ public DataMisalignedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_DATAMISALIGNED;
diff --git a/src/System.Private.CoreLib/shared/System/DateTime.cs b/src/System.Private.CoreLib/shared/System/DateTime.cs
index b5deefa94..5b76f6092 100644
--- a/src/System.Private.CoreLib/shared/System/DateTime.cs
+++ b/src/System.Private.CoreLib/shared/System/DateTime.cs
@@ -115,18 +115,18 @@ namespace System
public static readonly DateTime MaxValue = new DateTime(MaxTicks, DateTimeKind.Unspecified);
public static readonly DateTime UnixEpoch = new DateTime(UnixEpochTicks, DateTimeKind.Utc);
- private const UInt64 TicksMask = 0x3FFFFFFFFFFFFFFF;
- private const UInt64 FlagsMask = 0xC000000000000000;
- private const UInt64 LocalMask = 0x8000000000000000;
- private const Int64 TicksCeiling = 0x4000000000000000;
- private const UInt64 KindUnspecified = 0x0000000000000000;
- private const UInt64 KindUtc = 0x4000000000000000;
- private const UInt64 KindLocal = 0x8000000000000000;
- private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
- private const Int32 KindShift = 62;
-
- private const String TicksField = "ticks"; // Do not rename (binary serialization)
- private const String DateDataField = "dateData"; // Do not rename (binary serialization)
+ private const ulong TicksMask = 0x3FFFFFFFFFFFFFFF;
+ private const ulong FlagsMask = 0xC000000000000000;
+ private const ulong LocalMask = 0x8000000000000000;
+ private const long TicksCeiling = 0x4000000000000000;
+ private const ulong KindUnspecified = 0x0000000000000000;
+ private const ulong KindUtc = 0x4000000000000000;
+ private const ulong KindLocal = 0x8000000000000000;
+ private const ulong KindLocalAmbiguousDst = 0xC000000000000000;
+ private const int KindShift = 62;
+
+ private const string TicksField = "ticks"; // Do not rename (binary serialization)
+ private const string DateDataField = "dateData"; // Do not rename (binary serialization)
// The data is stored as an unsigned 64-bit integer
// Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value
@@ -136,7 +136,7 @@ namespace System
// savings time hour and it is in daylight savings time. This allows distinction of these
// otherwise ambiguous local times and prevents data loss when round tripping from Local to
// UTC time.
- private readonly UInt64 _dateData;
+ private readonly ulong _dateData;
// Constructs a DateTime from a tick count. The ticks
// argument specifies the date as the number of 100-nanosecond intervals
@@ -146,10 +146,10 @@ namespace System
{
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentOutOfRangeException(nameof(ticks), SR.ArgumentOutOfRange_DateTimeBadTicks);
- _dateData = (UInt64)ticks;
+ _dateData = (ulong)ticks;
}
- private DateTime(UInt64 dateData)
+ private DateTime(ulong dateData)
{
this._dateData = dateData;
}
@@ -164,17 +164,17 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
- internal DateTime(long ticks, DateTimeKind kind, Boolean isAmbiguousDst)
+ internal DateTime(long ticks, DateTimeKind kind, bool isAmbiguousDst)
{
if (ticks < MinTicks || ticks > MaxTicks)
{
throw new ArgumentOutOfRangeException(nameof(ticks), SR.ArgumentOutOfRange_DateTimeBadTicks);
}
Debug.Assert(kind == DateTimeKind.Local, "Internal Constructor is for local times only");
- _dateData = ((UInt64)ticks | (isAmbiguousDst ? KindLocalAmbiguousDst : KindLocal));
+ _dateData = ((ulong)ticks | (isAmbiguousDst ? KindLocalAmbiguousDst : KindLocal));
}
// Constructs a DateTime from a given year, month, and day. The
@@ -182,7 +182,7 @@ namespace System
//
public DateTime(int year, int month, int day)
{
- _dateData = (UInt64)DateToTicks(year, month, day);
+ _dateData = (ulong)DateToTicks(year, month, day);
}
// Constructs a DateTime from a given year, month, and day for
@@ -199,7 +199,7 @@ namespace System
//
public DateTime(int year, int month, int day, int hour, int minute, int second)
{
- _dateData = (UInt64)(DateToTicks(year, month, day) + TimeToTicks(hour, minute, second));
+ _dateData = (ulong)(DateToTicks(year, month, day) + TimeToTicks(hour, minute, second));
}
public DateTime(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind)
@@ -208,8 +208,8 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
// Constructs a DateTime from a given year, month, day, hour,
@@ -219,7 +219,7 @@ namespace System
{
if (calendar == null)
throw new ArgumentNullException(nameof(calendar));
- _dateData = (UInt64)calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ _dateData = (ulong)calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
}
// Constructs a DateTime from a given year, month, day, hour,
@@ -231,11 +231,11 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(millisecond), SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1));
}
- Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = (UInt64)ticks;
+ _dateData = (ulong)ticks;
}
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind)
@@ -248,11 +248,11 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
// Constructs a DateTime from a given year, month, day, hour,
@@ -266,11 +266,11 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(millisecond), SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1));
}
- Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ long ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = (UInt64)ticks;
+ _dateData = (ulong)ticks;
}
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind)
@@ -285,11 +285,11 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ long ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
private DateTime(SerializationInfo info, StreamingContext context)
@@ -297,10 +297,10 @@ namespace System
if (info == null)
throw new ArgumentNullException(nameof(info));
- Boolean foundTicks = false;
- Boolean foundDateData = false;
- Int64 serializedTicks = 0;
- UInt64 serializedDateData = 0;
+ bool foundTicks = false;
+ bool foundDateData = false;
+ long serializedTicks = 0;
+ ulong serializedDateData = 0;
// Get the data
@@ -328,13 +328,13 @@ namespace System
}
else if (foundTicks)
{
- _dateData = (UInt64)serializedTicks;
+ _dateData = (ulong)serializedTicks;
}
else
{
throw new SerializationException(SR.Serialization_MissingDateTimeData);
}
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
if (ticks < MinTicks || ticks > MaxTicks)
{
throw new SerializationException(SR.Serialization_DateTimeTicksOutOfRange);
@@ -343,15 +343,15 @@ namespace System
- internal Int64 InternalTicks
+ internal long InternalTicks
{
get
{
- return (Int64)(_dateData & TicksMask);
+ return (long)(_dateData & TicksMask);
}
}
- private UInt64 InternalKind
+ private ulong InternalKind
{
get
{
@@ -459,7 +459,7 @@ namespace System
}
int days = DaysInMonth(y, m);
if (d > days) d = days;
- return new DateTime((UInt64)(DateToTicks(y, m, d) + InternalTicks % TicksPerDay) | InternalKind);
+ return new DateTime((ulong)(DateToTicks(y, m, d) + InternalTicks % TicksPerDay) | InternalKind);
}
// Returns the DateTime resulting from adding a fractional number of
@@ -484,7 +484,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks + value) | InternalKind);
+ return new DateTime((ulong)(ticks + value) | InternalKind);
}
// Returns the DateTime resulting from adding the given number of
@@ -511,8 +511,8 @@ namespace System
//
public static int Compare(DateTime t1, DateTime t2)
{
- Int64 ticks1 = t1.InternalTicks;
- Int64 ticks2 = t2.InternalTicks;
+ long ticks1 = t1.InternalTicks;
+ long ticks2 = t2.InternalTicks;
if (ticks1 > ticks2) return 1;
if (ticks1 < ticks2) return -1;
return 0;
@@ -524,7 +524,7 @@ namespace System
// occurs. Null is considered less than any instance.
//
// Returns a value less than zero if this object
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null) return 1;
if (!(value is DateTime))
@@ -610,7 +610,7 @@ namespace System
// is equal to the value of this DateTime. Returns false
// otherwise.
//
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
if (value is DateTime)
{
@@ -633,15 +633,15 @@ namespace System
return t1.InternalTicks == t2.InternalTicks;
}
- public static DateTime FromBinary(Int64 dateData)
+ public static DateTime FromBinary(long dateData)
{
- if ((dateData & (unchecked((Int64)LocalMask))) != 0)
+ if ((dateData & (unchecked((long)LocalMask))) != 0)
{
// Local times need to be adjusted as you move from one time zone to another,
// just as they are when serializing in text. As such the format for local times
// changes to store the ticks of the UTC time, but with flags that look like a
// local date.
- Int64 ticks = dateData & (unchecked((Int64)TicksMask));
+ long ticks = dateData & (unchecked((long)TicksMask));
// Negative ticks are stored in the top part of the range and should be converted back into a negative number
if (ticks > TicksCeiling - TicksPerDay)
{
@@ -649,8 +649,8 @@ namespace System
}
// Convert the ticks back to local. If the UTC ticks are out of range, we need to default to
// the UTC offset from MinValue and MaxValue to be consistent with Parse.
- Boolean isAmbiguousLocalDst = false;
- Int64 offsetTicks;
+ bool isAmbiguousLocalDst = false;
+ long offsetTicks;
if (ticks < MinTicks)
{
offsetTicks = TimeZoneInfo.GetLocalUtcOffset(DateTime.MinValue, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
@@ -664,7 +664,7 @@ namespace System
// Because the ticks conversion between UTC and local is lossy, we need to capture whether the
// time is in a repeated hour so that it can be passed to the DateTime constructor.
DateTime utcDt = new DateTime(ticks, DateTimeKind.Utc);
- Boolean isDaylightSavings = false;
+ bool isDaylightSavings = false;
offsetTicks = TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
}
ticks += offsetTicks;
@@ -688,12 +688,12 @@ namespace System
// A version of ToBinary that uses the real representation and does not adjust local times. This is needed for
// scenarios where the serialized data must maintain compatibility
- internal static DateTime FromBinaryRaw(Int64 dateData)
+ internal static DateTime FromBinaryRaw(long dateData)
{
- Int64 ticks = dateData & (Int64)TicksMask;
+ long ticks = dateData & (long)TicksMask;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Argument_DateTimeBadBinaryData, nameof(dateData));
- return new DateTime((UInt64)dateData);
+ return new DateTime((ulong)dateData);
}
// Creates a DateTime from a Windows filetime. A Windows filetime is
@@ -736,7 +736,7 @@ namespace System
info.AddValue(DateDataField, _dateData);
}
- public Boolean IsDaylightSavingTime()
+ public bool IsDaylightSavingTime()
{
if (Kind == DateTimeKind.Utc)
{
@@ -750,7 +750,7 @@ namespace System
return new DateTime(value.InternalTicks, kind);
}
- public Int64 ToBinary()
+ public long ToBinary()
{
if (Kind == DateTimeKind.Local)
{
@@ -765,17 +765,17 @@ namespace System
// end of the maximum range, and values just below minimum value are stored
// at the end of the ticks area, just below 2^62.
TimeSpan offset = TimeZoneInfo.GetLocalUtcOffset(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- Int64 ticks = Ticks;
- Int64 storedTicks = ticks - offset.Ticks;
+ long ticks = Ticks;
+ long storedTicks = ticks - offset.Ticks;
if (storedTicks < 0)
{
storedTicks = TicksCeiling + storedTicks;
}
- return storedTicks | (unchecked((Int64)LocalMask));
+ return storedTicks | (unchecked((long)LocalMask));
}
else
{
- return (Int64)_dateData;
+ return (long)_dateData;
}
}
@@ -787,8 +787,8 @@ namespace System
{
get
{
- Int64 ticks = InternalTicks;
- return new DateTime((UInt64)(ticks - ticks % TicksPerDay) | InternalKind);
+ long ticks = InternalTicks;
+ return new DateTime((ulong)(ticks - ticks % TicksPerDay) | InternalKind);
}
}
@@ -796,7 +796,7 @@ namespace System
// to compute the year, day-of-year, month, or day part.
private int GetDatePart(int part)
{
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
// n = number of days since 1/1/0001
int n = (int)(ticks / TicksPerDay);
// y400 = number of whole 400-year periods since 1/1/0001
@@ -846,7 +846,7 @@ namespace System
// are needed rather than redoing the computations for each.
internal void GetDatePart(out int year, out int month, out int day)
{
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
// n = number of days since 1/1/0001
int n = (int)(ticks / TicksPerDay);
// y400 = number of whole 400-year periods since 1/1/0001
@@ -925,7 +925,7 @@ namespace System
//
public override int GetHashCode()
{
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
return unchecked((int)ticks) ^ (int)(ticks >> 32);
}
@@ -940,7 +940,7 @@ namespace System
}
}
- internal Boolean IsAmbiguousDaylightSavingTime()
+ internal bool IsAmbiguousDaylightSavingTime()
{
return (InternalKind == KindLocalAmbiguousDst);
}
@@ -1001,8 +1001,8 @@ namespace System
get
{
DateTime utc = UtcNow;
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utc, out isAmbiguousLocalDst).Ticks;
+ bool isAmbiguousLocalDst = false;
+ long offset = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utc, out isAmbiguousLocalDst).Ticks;
long tick = utc.Ticks + offset;
if (tick > DateTime.MaxTicks)
{
@@ -1089,7 +1089,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime Parse(String s)
+ public static DateTime Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return (DateTimeParse.Parse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None));
@@ -1099,13 +1099,13 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime Parse(String s, IFormatProvider provider)
+ public static DateTime Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), DateTimeStyles.None));
}
- public static DateTime Parse(String s, IFormatProvider provider, DateTimeStyles styles)
+ public static DateTime Parse(string s, IFormatProvider provider, DateTimeStyles styles)
{
DateTimeFormatInfo.ValidateStyles(styles, nameof(styles));
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -1122,7 +1122,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime ParseExact(String s, String format, IFormatProvider provider)
+ public static DateTime ParseExact(string s, string format, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
@@ -1133,7 +1133,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime ParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style)
+ public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -1141,20 +1141,13 @@ namespace System
return (DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style));
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static DateTime ParseExact(ReadOnlySpan<char> s, string format, IFormatProvider provider, DateTimeStyles style)
- {
- if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
- return ParseExact(s, (ReadOnlySpan<char>)format, provider, style);
- }
-
public static DateTime ParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, IFormatProvider provider, DateTimeStyles style = DateTimeStyles.None)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
return DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style);
}
- public static DateTime ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style)
+ public static DateTime ParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -1180,7 +1173,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks - valueTicks) | InternalKind);
+ return new DateTime((ulong)(ticks - valueTicks) | InternalKind);
}
// This function is duplicated in COMDateTime.cpp
@@ -1239,9 +1232,9 @@ namespace System
{
return this;
}
- Boolean isDaylightSavings = false;
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = TimeZoneInfo.GetUtcOffsetFromUtc(this, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
+ bool isDaylightSavings = false;
+ bool isAmbiguousLocalDst = false;
+ long offset = TimeZoneInfo.GetUtcOffsetFromUtc(this, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
long tick = Ticks + offset;
if (tick > DateTime.MaxTicks)
{
@@ -1260,59 +1253,55 @@ namespace System
return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
}
- public String ToLongDateString()
+ public string ToLongDateString()
{
- return DateTimeFormat.Format(this, "D", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "D", null);
}
- public String ToLongTimeString()
+ public string ToLongTimeString()
{
- return DateTimeFormat.Format(this, "T", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "T", null);
}
- public String ToShortDateString()
+ public string ToShortDateString()
{
- return DateTimeFormat.Format(this, "d", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "d", null);
}
- public String ToShortTimeString()
+ public string ToShortTimeString()
{
- return DateTimeFormat.Format(this, "t", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "t", null);
}
- public override String ToString()
+ public override string ToString()
{
- return DateTimeFormat.Format(this, null, DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, null, null);
}
- public String ToString(String format)
+ public string ToString(string format)
{
- return DateTimeFormat.Format(this, format, DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, format, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
- return DateTimeFormat.Format(this, null, DateTimeFormatInfo.GetInstance(provider));
+ return DateTimeFormat.Format(this, null, provider);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
- return DateTimeFormat.Format(this, format, DateTimeFormatInfo.GetInstance(provider));
+ return DateTimeFormat.Format(this, format, provider);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public bool TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider) =>
- TryFormat(destination, out charsWritten, (ReadOnlySpan<char>)format, provider);
-
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null) =>
- DateTimeFormat.TryFormat(this, destination, out charsWritten, format, DateTimeFormatInfo.GetInstance(provider));
+ DateTimeFormat.TryFormat(this, destination, out charsWritten, format, provider);
public DateTime ToUniversalTime()
{
return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
}
- public static Boolean TryParse(String s, out DateTime result)
+ public static bool TryParse(string s, out DateTime result)
{
if (s == null)
{
@@ -1327,7 +1316,7 @@ namespace System
return DateTimeParse.TryParse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out result);
}
- public static Boolean TryParse(String s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
+ public static bool TryParse(string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(styles, nameof(styles));
@@ -1346,7 +1335,7 @@ namespace System
return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result);
}
- public static Boolean TryParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
+ public static bool TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
@@ -1359,25 +1348,13 @@ namespace System
return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static bool TryParseExact(ReadOnlySpan<char> s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
- {
- if (format == null)
- {
- result = default;
- return false;
- }
-
- return TryParseExact(s, (ReadOnlySpan<char>)format, provider, style, out result);
- }
-
public static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result);
}
- public static Boolean TryParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result)
+ public static bool TryParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
@@ -1404,7 +1381,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(t), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks + valueTicks) | d.InternalKind);
+ return new DateTime((ulong)(ticks + valueTicks) | d.InternalKind);
}
public static DateTime operator -(DateTime d, TimeSpan t)
@@ -1415,7 +1392,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(t), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks - valueTicks) | d.InternalKind);
+ return new DateTime((ulong)(ticks - valueTicks) | d.InternalKind);
}
public static TimeSpan operator -(DateTime d1, DateTime d2)
@@ -1457,7 +1434,7 @@ namespace System
// Returns a string array containing all of the known date and time options for the
// current culture. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats()
+ public string[] GetDateTimeFormats()
{
return (GetDateTimeFormats(CultureInfo.CurrentCulture));
}
@@ -1465,7 +1442,7 @@ namespace System
// Returns a string array containing all of the known date and time options for the
// using the information provided by IFormatProvider. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats(IFormatProvider provider)
+ public string[] GetDateTimeFormats(IFormatProvider provider)
{
return (DateTimeFormat.GetAllDateTimes(this, DateTimeFormatInfo.GetInstance(provider)));
}
@@ -1474,7 +1451,7 @@ namespace System
// Returns a string array containing all of the date and time options for the
// given format format and current culture. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats(char format)
+ public string[] GetDateTimeFormats(char format)
{
return (GetDateTimeFormats(format, CultureInfo.CurrentCulture));
}
@@ -1482,7 +1459,7 @@ namespace System
// Returns a string array containing all of the date and time options for the
// given format format and given culture. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats(char format, IFormatProvider provider)
+ public string[] GetDateTimeFormats(char format, IFormatProvider provider)
{
return (DateTimeFormat.GetAllDateTimes(this, format, DateTimeFormatInfo.GetInstance(provider)));
}
@@ -1557,7 +1534,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Double"));
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Decimal"));
}
@@ -1567,7 +1544,7 @@ namespace System
return this;
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
@@ -1575,7 +1552,7 @@ namespace System
// Tries to construct a DateTime from a given year, month, day, hour,
// minute, second and millisecond.
//
- internal static Boolean TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result)
+ internal static bool TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result)
{
result = DateTime.MinValue;
if (year < 1 || year > 9999 || month < 1 || month > 12)
diff --git a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
index bb2196348..e89cbc6ca 100644
--- a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
+++ b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
@@ -31,11 +31,11 @@ namespace System
[StructLayout(LayoutKind.Auto)]
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback, ISpanFormattable
+ public readonly struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback, ISpanFormattable
{
// Constants
- internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
- internal const Int64 MinOffset = -MaxOffset;
+ internal const long MaxOffset = TimeSpan.TicksPerHour * 14;
+ internal const long MinOffset = -MaxOffset;
private const long UnixEpochSeconds = DateTime.UnixEpochTicks / TimeSpan.TicksPerSecond; // 62,135,596,800
private const long UnixEpochMilliseconds = DateTime.UnixEpochTicks / TimeSpan.TicksPerMillisecond; // 62,135,596,800,000
@@ -49,8 +49,8 @@ namespace System
public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(DateTime.UnixEpochTicks, TimeSpan.Zero);
// Instance Fields
- private DateTime _dateTime;
- private Int16 _offsetMinutes;
+ private readonly DateTime _dateTime;
+ private readonly short _offsetMinutes;
// Constructors
@@ -447,7 +447,7 @@ namespace System
// argument must be another DateTimeOffset, or otherwise an exception
// occurs. Null is considered less than any instance.
//
- int IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
if (obj == null) return 1;
if (!(obj is DateTimeOffset))
@@ -477,7 +477,7 @@ namespace System
// is equal to the value of this DateTimeOffset. Returns false
// otherwise.
//
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj is DateTimeOffset)
{
@@ -549,12 +549,12 @@ namespace System
// ----- SECTION: private serialization instance methods ----------------*
- void IDeserializationCallback.OnDeserialization(Object sender)
+ void IDeserializationCallback.OnDeserialization(object sender)
{
try
{
- _offsetMinutes = ValidateOffset(Offset);
- _dateTime = ValidateDate(ClockDateTime, Offset);
+ ValidateOffset(Offset);
+ ValidateDate(ClockDateTime, Offset);
}
catch (ArgumentException e)
{
@@ -583,7 +583,7 @@ namespace System
}
_dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); // Do not rename (binary serialization)
- _offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16)); // Do not rename (binary serialization)
+ _offsetMinutes = (short)info.GetValue("OffsetMinutes", typeof(short)); // Do not rename (binary serialization)
}
// Returns the hash code for this DateTimeOffset.
@@ -597,7 +597,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset Parse(String input)
+ public static DateTimeOffset Parse(string input)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -613,13 +613,13 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset Parse(String input, IFormatProvider formatProvider)
+ public static DateTimeOffset Parse(string input, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
return Parse(input, formatProvider, DateTimeStyles.None);
}
- public static DateTimeOffset Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles)
+ public static DateTimeOffset Parse(string input, IFormatProvider formatProvider, DateTimeStyles styles)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -643,7 +643,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider)
+ public static DateTimeOffset ParseExact(string input, string format, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
@@ -654,7 +654,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles)
+ public static DateTimeOffset ParseExact(string input, string format, IFormatProvider formatProvider, DateTimeStyles styles)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -669,13 +669,6 @@ namespace System
return new DateTimeOffset(dateResult.Ticks, offset);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static DateTimeOffset ParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, DateTimeStyles styles)
- {
- if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
- return ParseExact(input, (ReadOnlySpan<char>)format, formatProvider, styles);
- }
-
public static DateTimeOffset ParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, DateTimeStyles styles = DateTimeStyles.None)
{
styles = ValidateStyles(styles, nameof(styles));
@@ -683,7 +676,7 @@ namespace System
return new DateTimeOffset(dateResult.Ticks, offset);
}
- public static DateTimeOffset ParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles)
+ public static DateTimeOffset ParseExact(string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -760,43 +753,39 @@ namespace System
return new DateTimeOffset(UtcDateTime.ToLocalTime(throwOnOverflow));
}
- public override String ToString()
+ public override string ToString()
{
- return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.CurrentInfo, Offset);
+ return DateTimeFormat.Format(ClockDateTime, null, null, Offset);
}
- public String ToString(String format)
+ public string ToString(string format)
{
- return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.CurrentInfo, Offset);
+ return DateTimeFormat.Format(ClockDateTime, format, null, Offset);
}
- public String ToString(IFormatProvider formatProvider)
+ public string ToString(IFormatProvider formatProvider)
{
- return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ return DateTimeFormat.Format(ClockDateTime, null, formatProvider, Offset);
}
- public String ToString(String format, IFormatProvider formatProvider)
+ public string ToString(string format, IFormatProvider formatProvider)
{
- return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ return DateTimeFormat.Format(ClockDateTime, format, formatProvider, Offset);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public bool TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider) =>
- TryFormat(destination, out charsWritten, (ReadOnlySpan<char>)format, provider);
-
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider formatProvider = null) =>
- DateTimeFormat.TryFormat(ClockDateTime, destination, out charsWritten, format, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ DateTimeFormat.TryFormat(ClockDateTime, destination, out charsWritten, format, formatProvider, Offset);
public DateTimeOffset ToUniversalTime()
{
return new DateTimeOffset(UtcDateTime);
}
- public static Boolean TryParse(String input, out DateTimeOffset result)
+ public static bool TryParse(string input, out DateTimeOffset result)
{
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParse(input,
+ bool parsed = DateTimeParse.TryParse(input,
DateTimeFormatInfo.CurrentInfo,
DateTimeStyles.None,
out dateResult,
@@ -812,18 +801,18 @@ namespace System
return parsed;
}
- public static Boolean TryParse(String input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
+ public static bool TryParse(string input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null)
{
- result = default(DateTimeOffset);
+ result = default;
return false;
}
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParse(input,
+ bool parsed = DateTimeParse.TryParse(input,
DateTimeFormatInfo.GetInstance(formatProvider),
styles,
out dateResult,
@@ -840,19 +829,19 @@ namespace System
return parsed;
}
- public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles,
+ public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, DateTimeStyles styles,
out DateTimeOffset result)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null || format == null)
{
- result = default(DateTimeOffset);
+ result = default;
return false;
}
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParseExact(input,
+ bool parsed = DateTimeParse.TryParseExact(input,
format,
DateTimeFormatInfo.GetInstance(formatProvider),
styles,
@@ -862,18 +851,6 @@ namespace System
return parsed;
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static bool TryParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
- {
- if (format == null)
- {
- result = default;
- return false;
- }
-
- return TryParseExact(input, (ReadOnlySpan<char>)format, formatProvider, styles, out result);
- }
-
public static bool TryParseExact(
ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
{
@@ -883,19 +860,19 @@ namespace System
return parsed;
}
- public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles,
+ public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles,
out DateTimeOffset result)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null)
{
- result = default(DateTimeOffset);
+ result = default;
return false;
}
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParseExactMultiple(input,
+ bool parsed = DateTimeParse.TryParseExactMultiple(input,
formats,
DateTimeFormatInfo.GetInstance(formatProvider),
styles,
@@ -915,9 +892,9 @@ namespace System
}
// Ensures the TimeSpan is valid to go in a DateTimeOffset.
- private static Int16 ValidateOffset(TimeSpan offset)
+ private static short ValidateOffset(TimeSpan offset)
{
- Int64 ticks = offset.Ticks;
+ long ticks = offset.Ticks;
if (ticks % TimeSpan.TicksPerMinute != 0)
{
throw new ArgumentException(SR.Argument_OffsetPrecision, nameof(offset));
@@ -926,7 +903,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(offset), SR.Argument_OffsetOutOfRange);
}
- return (Int16)(offset.Ticks / TimeSpan.TicksPerMinute);
+ return (short)(offset.Ticks / TimeSpan.TicksPerMinute);
}
// Ensures that the time and offset are in range.
@@ -937,8 +914,8 @@ namespace System
Debug.Assert(offset.Ticks >= MinOffset && offset.Ticks <= MaxOffset, "Offset not validated.");
// This operation cannot overflow because offset should have already been validated to be within
- // 14 hours and the DateTime instance is more than that distance from the boundaries of Int64.
- Int64 utcTicks = dateTime.Ticks - offset.Ticks;
+ // 14 hours and the DateTime instance is more than that distance from the boundaries of long.
+ long utcTicks = dateTime.Ticks - offset.Ticks;
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
throw new ArgumentOutOfRangeException(nameof(offset), SR.Argument_UTCOutOfRange);
@@ -948,7 +925,7 @@ namespace System
return new DateTime(utcTicks, DateTimeKind.Unspecified);
}
- private static DateTimeStyles ValidateStyles(DateTimeStyles style, String parameterName)
+ private static DateTimeStyles ValidateStyles(DateTimeStyles style, string parameterName)
{
if ((style & DateTimeFormatInfo.InvalidDateTimeStyles) != 0)
{
diff --git a/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
new file mode 100644
index 000000000..22574c106
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
@@ -0,0 +1,2648 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+using X86 = System.Runtime.Intrinsics.X86;
+
+namespace System
+{
+ public partial struct Decimal
+ {
+ // Low level accessors used by a DecCalc and formatting
+ internal uint High => (uint)hi;
+ internal uint Low => (uint)lo;
+ internal uint Mid => (uint)mid;
+
+ internal bool IsNegative => flags < 0;
+
+ internal int Scale => (byte)(flags >> ScaleShift);
+
+#if BIGENDIAN
+ private ulong Low64 => ((ulong)Mid << 32) | Low;
+#else
+ private ulong Low64 => Unsafe.As<int, ulong>(ref Unsafe.AsRef(in lo));
+#endif
+
+ private static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As<decimal, DecCalc>(ref d);
+
+ #region APIs need by number formatting.
+
+ internal static uint DecDivMod1E9(ref decimal value)
+ {
+ return DecCalc.DecDivMod1E9(ref AsMutable(ref value));
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Class that contains all the mathematical calculations for decimal. Most of which have been ported from oleaut32.
+ /// </summary>
+ [StructLayout(LayoutKind.Explicit)]
+ private struct DecCalc
+ {
+ // NOTE: Do not change the offsets of these fields. This structure must have the same layout as Decimal.
+ [FieldOffset(0)]
+ private uint uflags;
+ [FieldOffset(4)]
+ private uint uhi;
+ [FieldOffset(8)]
+ private uint ulo;
+ [FieldOffset(12)]
+ private uint umid;
+
+ /// <summary>
+ /// The low and mid fields combined in little-endian order
+ /// </summary>
+ [FieldOffset(8)]
+ private ulong ulomidLE;
+
+ private uint High
+ {
+ get => uhi;
+ set => uhi = value;
+ }
+
+ private uint Low
+ {
+ get => ulo;
+ set => ulo = value;
+ }
+
+ private uint Mid
+ {
+ get => umid;
+ set => umid = value;
+ }
+
+ private bool IsNegative => (int)uflags < 0;
+
+ private int Scale => (byte)(uflags >> ScaleShift);
+
+ private ulong Low64
+ {
+#if BIGENDIAN
+ get { return ((ulong)umid << 32) | ulo; }
+ set { umid = (uint)(value >> 32); ulo = (uint)value; }
+#else
+ get => ulomidLE;
+ set => ulomidLE = value;
+#endif
+ }
+
+ private const uint SignMask = 0x80000000;
+ private const uint ScaleMask = 0x00FF0000;
+
+ private const int DEC_SCALE_MAX = 28;
+
+ private const uint TenToPowerNine = 1000000000;
+ private const ulong TenToPowerEighteen = 1000000000000000000;
+
+ // The maximum power of 10 that a 32 bit integer can store
+ private const int MaxInt32Scale = 9;
+ // The maximum power of 10 that a 64 bit integer can store
+ private const int MaxInt64Scale = 19;
+
+ // Fast access for 10^n where n is 0-9
+ private static readonly uint[] s_powers10 = new uint[] {
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000,
+ 1000000000
+ };
+
+ // Fast access for 10^n where n is 1-19
+ private static readonly ulong[] s_ulongPowers10 = new ulong[] {
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000,
+ 1000000000,
+ 10000000000,
+ 100000000000,
+ 1000000000000,
+ 10000000000000,
+ 100000000000000,
+ 1000000000000000,
+ 10000000000000000,
+ 100000000000000000,
+ 1000000000000000000,
+ 10000000000000000000,
+ };
+
+ private static readonly double[] s_doublePowers10 = new double[] {
+ 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
+ 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
+ 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
+ 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
+ 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
+ 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
+ 1e80
+ };
+
+ #region Decimal Math Helpers
+
+ private static unsafe uint GetExponent(float f)
+ {
+ // Based on pulling out the exp from this single struct layout
+ //typedef struct {
+ // ULONG mant:23;
+ // ULONG exp:8;
+ // ULONG sign:1;
+ //} SNGSTRUCT;
+
+ return (byte)(*(uint*)&f >> 23);
+ }
+
+ private static unsafe uint GetExponent(double d)
+ {
+ // Based on pulling out the exp from this double struct layout
+ //typedef struct {
+ // DWORDLONG mant:52;
+ // DWORDLONG signexp:12;
+ // } DBLSTRUCT;
+
+ return (uint)(*(ulong*)&d >> 52) & 0x7FFu;
+ }
+
+ private static ulong UInt32x32To64(uint a, uint b)
+ {
+ return (ulong)a * (ulong)b;
+ }
+
+ private static void UInt64x64To128(ulong a, ulong b, ref DecCalc pdecOut)
+ {
+ ulong low = UInt32x32To64((uint)a, (uint)b); // lo partial prod
+ ulong mid = UInt32x32To64((uint)a, (uint)(b >> 32)); // mid 1 partial prod
+ ulong high = UInt32x32To64((uint)(a >> 32), (uint)(b >> 32));
+ high += mid >> 32;
+ low += mid <<= 32;
+ if (low < mid) // test for carry
+ high++;
+
+ mid = UInt32x32To64((uint)(a >> 32), (uint)b);
+ high += mid >> 32;
+ low += mid <<= 32;
+ if (low < mid) // test for carry
+ high++;
+
+ if (high > uint.MaxValue)
+ throw new OverflowException(SR.Overflow_Decimal);
+ pdecOut.Low64 = low;
+ pdecOut.High = (uint)high;
+ }
+
+ /***
+ * Div96By32
+ *
+ * Entry:
+ * bufNum - 96-bit dividend as array of ULONGs, least-sig first
+ * ulDen - 32-bit divisor.
+ *
+ * Purpose:
+ * Do full divide, yielding 96-bit result and 32-bit remainder.
+ *
+ * Exit:
+ * Quotient overwrites dividend.
+ * Returns remainder.
+ *
+ * Exceptions:
+ * None.
+ *
+ ***********************************************************************/
+ private static uint Div96By32(ref Buf12 bufNum, uint ulDen)
+ {
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ ulong tmp, div;
+ if (bufNum.U2 != 0)
+ {
+ tmp = bufNum.High64;
+ div = tmp / ulDen;
+ bufNum.High64 = div;
+ tmp = ((tmp - (uint)div * ulDen) << 32) | bufNum.U0;
+ if (tmp == 0)
+ return 0;
+ uint div32 = (uint)(tmp / ulDen);
+ bufNum.U0 = div32;
+ return (uint)tmp - div32 * ulDen;
+ }
+
+ tmp = bufNum.Low64;
+ if (tmp == 0)
+ return 0;
+ div = tmp / ulDen;
+ bufNum.Low64 = div;
+ return (uint)(tmp - div * ulDen);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool Div96ByConst(ref ulong high64, ref uint low, uint pow)
+ {
+#if BIT64
+ ulong div64 = high64 / pow;
+ uint div = (uint)((((high64 - div64 * pow) << 32) + low) / pow);
+ if (low == div * pow)
+ {
+ high64 = div64;
+ low = div;
+ return true;
+ }
+#else
+ // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
+ Debug.Assert(pow <= ushort.MaxValue);
+ uint num, mid32, low16, div;
+ if (high64 <= uint.MaxValue)
+ {
+ num = (uint)high64;
+ mid32 = num / pow;
+ num = (num - mid32 * pow) << 16;
+
+ num += low >> 16;
+ low16 = num / pow;
+ num = (num - low16 * pow) << 16;
+
+ num += (ushort)low;
+ div = num / pow;
+ if (num == div * pow)
+ {
+ high64 = mid32;
+ low = (low16 << 16) + div;
+ return true;
+ }
+ }
+ else
+ {
+ num = (uint)(high64 >> 32);
+ uint high32 = num / pow;
+ num = (num - high32 * pow) << 16;
+
+ num += (uint)high64 >> 16;
+ mid32 = num / pow;
+ num = (num - mid32 * pow) << 16;
+
+ num += (ushort)high64;
+ div = num / pow;
+ num = (num - div * pow) << 16;
+ mid32 = div + (mid32 << 16);
+
+ num += low >> 16;
+ low16 = num / pow;
+ num = (num - low16 * pow) << 16;
+
+ num += (ushort)low;
+ div = num / pow;
+ if (num == div * pow)
+ {
+ high64 = ((ulong)high32 << 32) | mid32;
+ low = (low16 << 16) + div;
+ return true;
+ }
+ }
+#endif
+ return false;
+ }
+
+ // Normalize (unscale) the number by trying to divide out 10^8, 10^4, 10^2, and 10^1.
+ // If a division by one of these powers returns a zero remainder, then we keep the quotient.
+ //
+ // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10 we can extract.
+ // We use this as a quick test on whether to try a given power.
+ //
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void Unscale(ref uint low, ref ulong high64, ref int scale)
+ {
+#if BIT64
+ while ((byte)low == 0 && scale >= 8 && Div96ByConst(ref high64, ref low, 100000000))
+ scale -= 8;
+
+ if ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
+ scale -= 4;
+#else
+ while ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
+ scale -= 4;
+#endif
+
+ if ((low & 3) == 0 && scale >= 2 && Div96ByConst(ref high64, ref low, 100))
+ scale -= 2;
+
+ if ((low & 1) == 0 && scale >= 1 && Div96ByConst(ref high64, ref low, 10))
+ scale--;
+ }
+
+ /***
+ * Div96By64
+ *
+ * Entry:
+ * bufNum - 96-bit dividend as array of ULONGs, least-sig first
+ * sdlDen - 64-bit divisor.
+ *
+ * Purpose:
+ * Do partial divide, yielding 32-bit result and 64-bit remainder.
+ * Divisor must be larger than upper 64 bits of dividend.
+ *
+ * Exit:
+ * Remainder overwrites lower 64-bits of dividend.
+ * Returns quotient.
+ *
+ * Exceptions:
+ * None.
+ *
+ ***********************************************************************/
+ private static uint Div96By64(ref Buf12 bufNum, ulong den)
+ {
+ uint quo;
+ ulong num;
+ uint num2 = bufNum.U2;
+ if (num2 == 0)
+ {
+ num = bufNum.Low64;
+ if (num < den)
+ // Result is zero. Entire dividend is remainder.
+ return 0;
+
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ quo = (uint)(num / den);
+ num -= quo * den; // remainder
+ bufNum.Low64 = num;
+ return quo;
+ }
+
+ uint denHigh32 = (uint)(den >> 32);
+ if (num2 >= denHigh32)
+ {
+ // Divide would overflow. Assume a quotient of 2^32, and set
+ // up remainder accordingly.
+ //
+ num = bufNum.Low64;
+ num -= den << 32;
+ quo = 0;
+
+ // Remainder went negative. Add divisor back in until it's positive,
+ // a max of 2 times.
+ //
+ do
+ {
+ quo--;
+ num += den;
+ } while (num >= den);
+
+ bufNum.Low64 = num;
+ return quo;
+ }
+
+ // Hardware divide won't overflow
+ //
+ ulong num64 = bufNum.High64;
+ if (num64 < denHigh32)
+ // Result is zero. Entire dividend is remainder.
+ //
+ return 0;
+
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ quo = (uint)(num64 / denHigh32);
+ num = bufNum.U0 | ((num64 - quo * denHigh32) << 32); // remainder
+
+ // Compute full remainder, rem = dividend - (quo * divisor).
+ //
+ ulong prod = UInt32x32To64(quo, (uint)den); // quo * lo divisor
+ num -= prod;
+
+ if (num > ~prod)
+ {
+ // Remainder went negative. Add divisor back in until it's positive,
+ // a max of 2 times.
+ //
+ do
+ {
+ quo--;
+ num += den;
+ } while (num >= den);
+ }
+
+ bufNum.Low64 = num;
+ return quo;
+ }
+
+ /***
+ * Div128By96
+ *
+ * Entry:
+ * bufNum - 128-bit dividend as array of ULONGs, least-sig first
+ * bufDen - 96-bit divisor.
+ *
+ * Purpose:
+ * Do partial divide, yielding 32-bit result and 96-bit remainder.
+ * Top divisor ULONG must be larger than top dividend ULONG. This is
+ * assured in the initial call because the divisor is normalized
+ * and the dividend can't be. In subsequent calls, the remainder
+ * is multiplied by 10^9 (max), so it can be no more than 1/4 of
+ * the divisor which is effectively multiplied by 2^32 (4 * 10^9).
+ *
+ * Exit:
+ * Remainder overwrites lower 96-bits of dividend.
+ * Returns quotient.
+ *
+ * Exceptions:
+ * None.
+ *
+ ***********************************************************************/
+ private static uint Div128By96(ref Buf16 bufNum, ref Buf12 bufDen)
+ {
+ ulong dividend = bufNum.High64;
+ uint den = bufDen.U2;
+ if (dividend < den)
+ // Result is zero. Entire dividend is remainder.
+ //
+ return 0;
+
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ uint quo = (uint)(dividend / den);
+ uint remainder = (uint)dividend - quo * den;
+
+ // Compute full remainder, rem = dividend - (quo * divisor).
+ //
+ ulong prod1 = UInt32x32To64(quo, bufDen.U0); // quo * lo divisor
+ ulong prod2 = UInt32x32To64(quo, bufDen.U1); // quo * mid divisor
+ prod2 += prod1 >> 32;
+ prod1 = (uint)prod1 | (prod2 << 32);
+ prod2 >>= 32;
+
+ ulong num = bufNum.Low64;
+ num -= prod1;
+ remainder -= (uint)prod2;
+
+ // Propagate carries
+ //
+ if (num > ~prod1)
+ {
+ remainder--;
+ if (remainder < ~(uint)prod2)
+ goto PosRem;
+ }
+ else if (remainder <= ~(uint)prod2)
+ goto PosRem;
+ {
+ // Remainder went negative. Add divisor back in until it's positive,
+ // a max of 2 times.
+ //
+ prod1 = bufDen.Low64;
+
+ for (;;)
+ {
+ quo--;
+ num += prod1;
+ remainder += den;
+
+ if (num < prod1)
+ {
+ // Detected carry. Check for carry out of top
+ // before adding it in.
+ //
+ if (remainder++ < den)
+ break;
+ }
+ if (remainder < den)
+ break; // detected carry
+ }
+ }
+PosRem:
+
+ bufNum.Low64 = num;
+ bufNum.U2 = remainder;
+ return quo;
+ }
+
+ /***
+ * IncreaseScale
+ *
+ * Entry:
+ * bufNum - 96-bit number as array of ULONGs, least-sig first
+ * ulPwr - Scale factor to multiply by
+ *
+ * Purpose:
+ * Multiply the two numbers. The low 96 bits of the result overwrite
+ * the input. The last 32 bits of the product are the return value.
+ *
+ * Exit:
+ * Returns highest 32 bits of product.
+ *
+ * Exceptions:
+ * None.
+ *
+ ***********************************************************************/
+ private static uint IncreaseScale(ref Buf12 bufNum, uint ulPwr)
+ {
+ ulong tmp = UInt32x32To64(bufNum.U0, ulPwr);
+ bufNum.U0 = (uint)tmp;
+ tmp >>= 32;
+ tmp += UInt32x32To64(bufNum.U1, ulPwr);
+ bufNum.U1 = (uint)tmp;
+ tmp >>= 32;
+ tmp += UInt32x32To64(bufNum.U2, ulPwr);
+ bufNum.U2 = (uint)tmp;
+ return (uint)(tmp >> 32);
+ }
+
+ private static void IncreaseScale64(ref Buf12 bufNum, uint ulPwr)
+ {
+ ulong tmp = UInt32x32To64(bufNum.U0, ulPwr);
+ bufNum.U0 = (uint)tmp;
+ tmp >>= 32;
+ tmp += UInt32x32To64(bufNum.U1, ulPwr);
+ bufNum.High64 = tmp;
+ }
+
+ /***
+ * ScaleResult
+ *
+ * Entry:
+ * bufRes - Array of ULONGs with value, least-significant first.
+ * iHiRes - Index of last non-zero value in bufRes.
+ * iScale - Scale factor for this value, range 0 - 2 * DEC_SCALE_MAX
+ *
+ * Purpose:
+ * See if we need to scale the result to fit it in 96 bits.
+ * Perform needed scaling. Adjust scale factor accordingly.
+ *
+ * Exit:
+ * bufRes updated in place, always 3 ULONGs.
+ * New scale factor returned.
+ *
+ ***********************************************************************/
+ private static unsafe int ScaleResult(Buf24* bufRes, uint iHiRes, int iScale)
+ {
+ Debug.Assert(iHiRes < bufRes->Length);
+ uint* rgulRes = (uint*)bufRes;
+
+ // See if we need to scale the result. The combined scale must
+ // be <= DEC_SCALE_MAX and the upper 96 bits must be zero.
+ //
+ // Start by figuring a lower bound on the scaling needed to make
+ // the upper 96 bits zero. iHiRes is the index into rgulRes[]
+ // of the highest non-zero ULONG.
+ //
+ int iNewScale = 0;
+ if (iHiRes > 2)
+ {
+ iNewScale = (int)iHiRes * 32 - 64 - 1;
+ iNewScale -= X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(rgulRes[iHiRes]) : LeadingZeroCount(rgulRes[iHiRes]);
+
+ // Multiply bit position by log10(2) to figure it's power of 10.
+ // We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
+ // with a multiply saves a 96-byte lookup table. The power returned
+ // is <= the power of the number, so we must add one power of 10
+ // to make it's integer part zero after dividing by 256.
+ //
+ // Note: the result of this multiplication by an approximation of
+ // log10(2) have been exhaustively checked to verify it gives the
+ // correct result. (There were only 95 to check...)
+ //
+ iNewScale = ((iNewScale * 77) >> 8) + 1;
+
+ // iNewScale = min scale factor to make high 96 bits zero, 0 - 29.
+ // This reduces the scale factor of the result. If it exceeds the
+ // current scale of the result, we'll overflow.
+ //
+ if (iNewScale > iScale)
+ goto ThrowOverflow;
+ }
+
+ // Make sure we scale by enough to bring the current scale factor
+ // into valid range.
+ //
+ if (iNewScale < iScale - DEC_SCALE_MAX)
+ iNewScale = iScale - DEC_SCALE_MAX;
+
+ if (iNewScale != 0)
+ {
+ // Scale by the power of 10 given by iNewScale. Note that this is
+ // NOT guaranteed to bring the number within 96 bits -- it could
+ // be 1 power of 10 short.
+ //
+ iScale -= iNewScale;
+ uint ulSticky = 0;
+ uint quotient, remainder = 0;
+
+ for (;;)
+ {
+ ulSticky |= remainder; // record remainder as sticky bit
+
+ uint ulPwr;
+ // Scaling loop specialized for each power of 10 because division by constant is an order of magnitude faster (especially for 64-bit division that's actually done by 128bit DIV on x64)
+ switch (iNewScale)
+ {
+ case 1:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 10);
+ break;
+ case 2:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 100);
+ break;
+ case 3:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 1000);
+ break;
+ case 4:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 10000);
+ break;
+#if BIT64
+ case 5:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 100000);
+ break;
+ case 6:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 1000000);
+ break;
+ case 7:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 10000000);
+ break;
+ case 8:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 100000000);
+ break;
+ default:
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, TenToPowerNine);
+ break;
+#else
+ default:
+ goto case 4;
+#endif
+ }
+ rgulRes[iHiRes] = quotient;
+ // If first quotient was 0, update iHiRes.
+ //
+ if (quotient == 0 && iHiRes != 0)
+ iHiRes--;
+
+#if BIT64
+ iNewScale -= MaxInt32Scale;
+#else
+ iNewScale -= 4;
+#endif
+ if (iNewScale > 0)
+ continue; // scale some more
+
+ // If we scaled enough, iHiRes would be 2 or less. If not,
+ // divide by 10 more.
+ //
+ if (iHiRes > 2)
+ {
+ if (iScale == 0)
+ goto ThrowOverflow;
+ iNewScale = 1;
+ iScale--;
+ continue; // scale by 10
+ }
+
+ // Round final result. See if remainder >= 1/2 of divisor.
+ // If remainder == 1/2 divisor, round up if odd or sticky bit set.
+ //
+ ulPwr >>= 1; // power of 10 always even
+ if (ulPwr <= remainder && (ulPwr < remainder || ((rgulRes[0] & 1) | ulSticky) != 0) && ++rgulRes[0] == 0)
+ {
+ uint iCur = 0;
+ do
+ {
+ Debug.Assert(iCur + 1 < bufRes->Length);
+ }
+ while (++rgulRes[++iCur] == 0);
+
+ if (iCur > 2)
+ {
+ // The rounding caused us to carry beyond 96 bits.
+ // Scale by 10 more.
+ //
+ if (iScale == 0)
+ goto ThrowOverflow;
+ iHiRes = iCur;
+ ulSticky = 0; // no sticky bit
+ remainder = 0; // or remainder
+ iNewScale = 1;
+ iScale--;
+ continue; // scale by 10
+ }
+ }
+
+ break;
+ } // for(;;)
+ }
+ return iScale;
+
+ThrowOverflow:
+ throw new OverflowException(SR.Overflow_Decimal);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static unsafe uint DivByConst(uint* rgulRes, uint iHiRes, out uint quotient, out uint remainder, uint power)
+ {
+ uint high = rgulRes[iHiRes];
+ remainder = high - (quotient = high / power) * power;
+ for (uint i = iHiRes - 1; (int)i >= 0; i--)
+ {
+#if BIT64
+ ulong num = rgulRes[i] + ((ulong)remainder << 32);
+ remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
+#else
+ // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
+ Debug.Assert(power <= ushort.MaxValue);
+#if BIGENDIAN
+ const int low16 = 2, high16 = 0;
+#else
+ const int low16 = 0, high16 = 2;
+#endif
+ // byte* is used here because Roslyn doesn't do constant propagation for pointer arithmetic
+ uint num = *(ushort*)((byte*)rgulRes + i * 4 + high16) + (remainder << 16);
+ uint div = num / power;
+ remainder = num - div * power;
+ *(ushort*)((byte*)rgulRes + i * 4 + high16) = (ushort)div;
+
+ num = *(ushort*)((byte*)rgulRes + i * 4 + low16) + (remainder << 16);
+ div = num / power;
+ remainder = num - div * power;
+ *(ushort*)((byte*)rgulRes + i * 4 + low16) = (ushort)div;
+#endif
+ }
+ return power;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LeadingZeroCount(uint value)
+ {
+ Debug.Assert(value > 0);
+ int c = 1;
+ if ((value & 0xFFFF0000) == 0)
+ {
+ value <<= 16;
+ c += 16;
+ }
+ if ((value & 0xFF000000) == 0)
+ {
+ value <<= 8;
+ c += 8;
+ }
+ if ((value & 0xF0000000) == 0)
+ {
+ value <<= 4;
+ c += 4;
+ }
+ if ((value & 0xC0000000) == 0)
+ {
+ value <<= 2;
+ c += 2;
+ }
+ return c + ((int)value >> 31);
+ }
+
+ // Adjust the quotient to deal with an overflow. We need to divide by 10,
+ // feed in the high bit to undo the overflow and then round as required,
+ private static int OverflowUnscale(ref Buf12 bufQuo, int iScale, bool fRemainder)
+ {
+ if (--iScale < 0)
+ throw new OverflowException(SR.Overflow_Decimal);
+
+ Debug.Assert(bufQuo.U2 == 0);
+
+ // We have overflown, so load the high bit with a one.
+ const ulong highbit = 1UL << 32;
+ bufQuo.U2 = (uint)(highbit / 10);
+ ulong tmp = ((highbit % 10) << 32) + bufQuo.U1;
+ uint div = (uint)(tmp / 10);
+ bufQuo.U1 = div;
+ tmp = ((tmp - div * 10) << 32) + bufQuo.U0;
+ div = (uint)(tmp / 10);
+ bufQuo.U0 = div;
+ uint remainder = (uint)(tmp - div * 10);
+ // The remainder is the last digit that does not fit, so we can use it to work out if we need to round up
+ if (remainder > 5 || remainder == 5 && (fRemainder || (bufQuo.U0 & 1) != 0))
+ Add32To96(ref bufQuo, 1);
+ return iScale;
+ }
+
+ /***
+ * SearchScale
+ *
+ * Entry:
+ * bufQuo - 96-bit quotient
+ * iScale - Scale factor of quotient, range -DEC_SCALE_MAX to DEC_SCALE_MAX-1
+ *
+ * Purpose:
+ * Determine the max power of 10, <= 9, that the quotient can be scaled
+ * up by and still fit in 96 bits.
+ *
+ * Exit:
+ * Returns power of 10 to scale by.
+ *
+ ***********************************************************************/
+ private static int SearchScale(ref Buf12 bufQuo, int iScale)
+ {
+ const uint OVFL_MAX_9_HI = 4;
+ const uint OVFL_MAX_8_HI = 42;
+ const uint OVFL_MAX_7_HI = 429;
+ const uint OVFL_MAX_6_HI = 4294;
+ const uint OVFL_MAX_5_HI = 42949;
+ const uint OVFL_MAX_4_HI = 429496;
+ const uint OVFL_MAX_3_HI = 4294967;
+ const uint OVFL_MAX_2_HI = 42949672;
+ const uint OVFL_MAX_1_HI = 429496729;
+ const ulong OVFL_MAX_9_MIDLO = 5441186219426131129;
+
+ uint ulResHi = bufQuo.U2;
+ ulong ulResMidLo = bufQuo.Low64;
+ int iCurScale = 0;
+
+ // Quick check to stop us from trying to scale any more.
+ //
+ if (ulResHi > OVFL_MAX_1_HI)
+ {
+ goto HaveScale;
+ }
+
+ var powerOvfl = PowerOvflValues;
+ if (iScale > DEC_SCALE_MAX - 9)
+ {
+ // We can't scale by 10^9 without exceeding the max scale factor.
+ // See if we can scale to the max. If not, we'll fall into
+ // standard search for scale factor.
+ //
+ iCurScale = DEC_SCALE_MAX - iScale;
+ if (ulResHi < powerOvfl[iCurScale - 1].Hi)
+ goto HaveScale;
+ }
+ else if (ulResHi < OVFL_MAX_9_HI || ulResHi == OVFL_MAX_9_HI && ulResMidLo <= OVFL_MAX_9_MIDLO)
+ return 9;
+
+ // Search for a power to scale by < 9. Do a binary search.
+ //
+ if (ulResHi > OVFL_MAX_5_HI)
+ {
+ if (ulResHi > OVFL_MAX_3_HI)
+ {
+ iCurScale = 2;
+ if (ulResHi > OVFL_MAX_2_HI)
+ iCurScale--;
+ }
+ else
+ {
+ iCurScale = 4;
+ if (ulResHi > OVFL_MAX_4_HI)
+ iCurScale--;
+ }
+ }
+ else
+ {
+ if (ulResHi > OVFL_MAX_7_HI)
+ {
+ iCurScale = 6;
+ if (ulResHi > OVFL_MAX_6_HI)
+ iCurScale--;
+ }
+ else
+ {
+ iCurScale = 8;
+ if (ulResHi > OVFL_MAX_8_HI)
+ iCurScale--;
+ }
+ }
+
+ // In all cases, we already found we could not use the power one larger.
+ // So if we can use this power, it is the biggest, and we're done. If
+ // we can't use this power, the one below it is correct for all cases
+ // unless it's 10^1 -- we might have to go to 10^0 (no scaling).
+ //
+ if (ulResHi == powerOvfl[iCurScale - 1].Hi && ulResMidLo > powerOvfl[iCurScale - 1].MidLo)
+ iCurScale--;
+
+ HaveScale:
+ // iCurScale = largest power of 10 we can scale by without overflow,
+ // iCurScale < 9. See if this is enough to make scale factor
+ // positive if it isn't already.
+ //
+ if (iCurScale + iScale < 0)
+ throw new OverflowException(SR.Overflow_Decimal);
+
+ return iCurScale;
+ }
+
+ // Add a 32 bit unsigned long to an array of 3 unsigned longs representing a 96 integer
+ // Returns false if there is an overflow
+ private static bool Add32To96(ref Buf12 bufNum, uint ulValue)
+ {
+ if ((bufNum.Low64 += ulValue) < ulValue)
+ {
+ if (++bufNum.U2 == 0)
+ return false;
+ }
+ return true;
+ }
+
+ // DecAddSub adds or subtracts two decimal values.
+ // On return, d1 contains the result of the operation and d2 is trashed.
+ // Passing in true for bSign means subtract and false means add.
+ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool bSign)
+ {
+ ulong low64 = d1.Low64;
+ uint high = d1.High, flags = d1.uflags, d2flags = d2.uflags;
+
+ uint xorflags = d2flags ^ flags;
+ bSign ^= (xorflags & SignMask) != 0;
+
+ if ((xorflags & ScaleMask) == 0)
+ {
+ // Scale factors are equal, no alignment necessary.
+ //
+ goto AlignedAdd;
+ }
+ else
+ {
+ // Scale factors are not equal. Assume that a larger scale
+ // factor (more decimal places) is likely to mean that number
+ // is smaller. Start by guessing that the right operand has
+ // the larger scale factor. The result will have the larger
+ // scale factor.
+ //
+ uint d1flags = flags;
+ flags = d2flags & ScaleMask | flags & SignMask; // scale factor of "smaller", but sign of "larger"
+ int iScale = (int)(flags - d1flags) >> ScaleShift;
+
+ if (iScale < 0)
+ {
+ // Guessed scale factor wrong. Swap operands.
+ //
+ iScale = -iScale;
+ flags = d1flags;
+ if (bSign)
+ flags ^= SignMask;
+ low64 = d2.Low64;
+ high = d2.High;
+ d2 = d1;
+ }
+
+ uint ulPwr;
+ ulong tmp64, tmpLow;
+
+ // d1 will need to be multiplied by 10^iScale so
+ // it will have the same scale as d2. We could be
+ // extending it to up to 192 bits of precision.
+
+ // Scan for zeros in the upper words.
+ //
+ if (high == 0)
+ {
+ if (low64 <= uint.MaxValue)
+ {
+ if ((uint)low64 == 0)
+ {
+ // Left arg is zero, return right.
+ //
+ uint signFlags = flags & SignMask;
+ if (bSign)
+ signFlags ^= SignMask;
+ d1 = d2;
+ d1.uflags = d2.uflags & ScaleMask | signFlags;
+ return;
+ }
+
+ do
+ {
+ if (iScale <= MaxInt32Scale)
+ {
+ low64 = UInt32x32To64((uint)low64, s_powers10[iScale]);
+ goto AlignedAdd;
+ }
+ iScale -= MaxInt32Scale;
+ low64 = UInt32x32To64((uint)low64, TenToPowerNine);
+ } while (low64 <= uint.MaxValue);
+ }
+
+ do
+ {
+ ulPwr = TenToPowerNine;
+ if (iScale < MaxInt32Scale)
+ ulPwr = s_powers10[iScale];
+ tmpLow = UInt32x32To64((uint)low64, ulPwr);
+ tmp64 = UInt32x32To64((uint)(low64 >> 32), ulPwr) + (tmpLow >> 32);
+ low64 = (uint)tmpLow + (tmp64 << 32);
+ high = (uint)(tmp64 >> 32);
+ if ((iScale -= MaxInt32Scale) <= 0)
+ goto AlignedAdd;
+ } while (high == 0);
+ }
+
+ while (true)
+ {
+ // Scaling won't make it larger than 4 ULONGs
+ //
+ ulPwr = TenToPowerNine;
+ if (iScale < MaxInt32Scale)
+ ulPwr = s_powers10[iScale];
+ tmpLow = UInt32x32To64((uint)low64, ulPwr);
+ tmp64 = UInt32x32To64((uint)(low64 >> 32), ulPwr) + (tmpLow >> 32);
+ low64 = (uint)tmpLow + (tmp64 << 32);
+ tmp64 >>= 32;
+ tmp64 += UInt32x32To64(high, ulPwr);
+
+ iScale -= MaxInt32Scale;
+ if (tmp64 > uint.MaxValue)
+ break;
+
+ high = (uint)tmp64;
+ // Result fits in 96 bits. Use standard aligned add.
+ if (iScale <= 0)
+ goto AlignedAdd;
+ }
+
+ // Have to scale by a bunch. Move the number to a buffer where it has room to grow as it's scaled.
+ //
+ Buf24 bufNum;
+ _ = &bufNum; // workaround for CS0165
+ bufNum.Low64 = low64;
+ bufNum.Mid64 = tmp64;
+ uint iHiProd = 3;
+
+ // Scaling loop, up to 10^9 at a time. iHiProd stays updated with index of highest non-zero ULONG.
+ //
+ for (; iScale > 0; iScale -= MaxInt32Scale)
+ {
+ ulPwr = TenToPowerNine;
+ if (iScale < MaxInt32Scale)
+ ulPwr = s_powers10[iScale];
+ tmp64 = 0;
+ uint* rgulNum = (uint*)&bufNum;
+ for (uint iCur = 0; ;)
+ {
+ Debug.Assert(iCur < bufNum.Length);
+ tmp64 += UInt32x32To64(rgulNum[iCur], ulPwr);
+ rgulNum[iCur] = (uint)tmp64;
+ iCur++;
+ tmp64 >>= 32;
+ if (iCur > iHiProd)
+ break;
+ }
+
+ if ((uint)tmp64 != 0)
+ {
+ // We're extending the result by another ULONG.
+ Debug.Assert(iHiProd + 1 < bufNum.Length);
+ rgulNum[++iHiProd] = (uint)tmp64;
+ }
+ }
+
+ // Scaling complete, do the add. Could be subtract if signs differ.
+ //
+ tmp64 = bufNum.Low64;
+ low64 = d2.Low64;
+ uint tmpHigh = bufNum.U2;
+ high = d2.High;
+
+ if (bSign)
+ {
+ // Signs differ, subtract.
+ //
+ low64 = tmp64 - low64;
+ high = tmpHigh - high;
+
+ // Propagate carry
+ //
+ if (low64 > tmp64)
+ {
+ high--;
+ if (high < tmpHigh)
+ goto NoCarry;
+ }
+ else if (high <= tmpHigh)
+ goto NoCarry;
+
+ // Carry the subtraction into the higher bits.
+ //
+ uint* rgulNum = (uint*)&bufNum;
+ uint iCur = 3;
+ do
+ {
+ Debug.Assert(iCur < bufNum.Length);
+ } while (rgulNum[iCur++]-- == 0);
+ Debug.Assert(iHiProd < bufNum.Length);
+ if (rgulNum[iHiProd] == 0 && --iHiProd <= 2)
+ goto ReturnResult;
+ }
+ else
+ {
+ // Signs the same, add.
+ //
+ low64 += tmp64;
+ high += tmpHigh;
+
+ // Propagate carry
+ //
+ if (low64 < tmp64)
+ {
+ high++;
+ if (high > tmpHigh)
+ goto NoCarry;
+ }
+ else if (high >= tmpHigh)
+ goto NoCarry;
+
+ uint* rgulNum = (uint*)&bufNum;
+ for (uint iCur = 3; ++rgulNum[iCur++] == 0;)
+ {
+ Debug.Assert(iCur < bufNum.Length);
+ if (iHiProd < iCur)
+ {
+ rgulNum[iCur] = 1;
+ iHiProd = iCur;
+ break;
+ }
+ }
+ }
+NoCarry:
+
+ bufNum.Low64 = low64;
+ bufNum.U2 = high;
+ int scale = ScaleResult(&bufNum, iHiProd, (byte)(flags >> ScaleShift));
+ flags = (flags & ~ScaleMask) | ((uint)scale << ScaleShift);
+ low64 = bufNum.Low64;
+ high = bufNum.U2;
+ goto ReturnResult;
+ }
+
+SignFlip:
+ {
+ // Got negative result. Flip its sign.
+ flags ^= SignMask;
+ high = ~high;
+ low64 = (ulong)-(long)low64;
+ if (low64 == 0)
+ high++;
+ goto ReturnResult;
+ }
+
+AlignedScale:
+ {
+ // The addition carried above 96 bits.
+ // Divide the value by 10, dropping the scale factor.
+ //
+ if ((flags & ScaleMask) == 0)
+ throw new OverflowException(SR.Overflow_Decimal);
+ flags -= 1 << ScaleShift;
+
+ const uint den = 10;
+ ulong num = high + (1UL << 32);
+ high = (uint)(num / den);
+ num = ((num - high * den) << 32) + (low64 >> 32);
+ uint div = (uint)(num / den);
+ num = ((num - div * den) << 32) + (uint)low64;
+ low64 = div;
+ low64 <<= 32;
+ div = (uint)(num / den);
+ low64 += div;
+ div = (uint)num - div * den;
+
+ // See if we need to round up.
+ //
+ if (div >= 5 && (div > 5 || (low64 & 1) != 0))
+ {
+ if (++low64 == 0)
+ high++;
+ }
+ goto ReturnResult;
+ }
+
+AlignedAdd:
+ {
+ ulong d1Low64 = low64;
+ uint d1High = high;
+ if (bSign)
+ {
+ // Signs differ - subtract
+ //
+ low64 = d1Low64 - d2.Low64;
+ high = d1High - d2.High;
+
+ // Propagate carry
+ //
+ if (low64 > d1Low64)
+ {
+ high--;
+ if (high >= d1High)
+ goto SignFlip;
+ }
+ else if (high > d1High)
+ goto SignFlip;
+ }
+ else
+ {
+ // Signs are the same - add
+ //
+ low64 = d1Low64 + d2.Low64;
+ high = d1High + d2.High;
+
+ // Propagate carry
+ //
+ if (low64 < d1Low64)
+ {
+ high++;
+ if (high <= d1High)
+ goto AlignedScale;
+ }
+ else if (high < d1High)
+ goto AlignedScale;
+ }
+ goto ReturnResult;
+ }
+
+ReturnResult:
+ d1.uflags = flags;
+ d1.High = high;
+ d1.Low64 = low64;
+ return;
+ }
+
+#endregion
+
+ //**********************************************************************
+ // VarCyFromDec - Convert Currency to Decimal (similar to OleAut32 api.)
+ //**********************************************************************
+ internal static long VarCyFromDec(ref DecCalc pdecIn)
+ {
+ long value;
+
+ int scale = pdecIn.Scale - 4;
+ // Need to scale to get 4 decimal places. -4 <= scale <= 24.
+ //
+ if (scale < 0)
+ {
+ if (pdecIn.High != 0)
+ goto ThrowOverflow;
+ uint pwr = s_powers10[-scale];
+ ulong high = UInt32x32To64(pwr, pdecIn.Mid);
+ if (high > uint.MaxValue)
+ goto ThrowOverflow;
+ ulong low = UInt32x32To64(pwr, pdecIn.Low);
+ low += high <<= 32;
+ if (low < high)
+ goto ThrowOverflow;
+ value = (long)low;
+ }
+ else
+ {
+ if (scale != 0)
+ InternalRound(ref pdecIn, (uint)scale, RoundingMode.ToEven);
+ if (pdecIn.High != 0)
+ goto ThrowOverflow;
+ value = (long)pdecIn.Low64;
+ }
+
+ if (value < 0 && (value != long.MinValue || !pdecIn.IsNegative))
+ goto ThrowOverflow;
+
+ if (pdecIn.IsNegative)
+ value = -value;
+
+ return value;
+
+ThrowOverflow:
+ throw new OverflowException(SR.Overflow_Currency);
+ }
+
+ //**********************************************************************
+ // VarDecCmp - Decimal Compare updated to return values similar to ICompareTo
+ //**********************************************************************
+ internal static int VarDecCmp(in decimal pdecL, in decimal pdecR)
+ {
+ if ((pdecR.Low | pdecR.Mid | pdecR.High) == 0)
+ {
+ if ((pdecL.Low | pdecL.Mid | pdecL.High) == 0)
+ return 0;
+ return (pdecL.flags >> 31) | 1;
+ }
+ if ((pdecL.Low | pdecL.Mid | pdecL.High) == 0)
+ return -((pdecR.flags >> 31) | 1);
+
+ int sign = (pdecL.flags >> 31) - (pdecR.flags >> 31);
+ if (sign != 0)
+ return sign;
+ return VarDecCmpSub(in pdecL, in pdecR);
+ }
+
+ private static int VarDecCmpSub(in decimal d1, in decimal d2)
+ {
+ int flags = d2.flags;
+ int sign = (flags >> 31) | 1;
+ int iScale = flags - d1.flags;
+
+ ulong low64 = d1.Low64;
+ uint high = d1.High;
+
+ ulong d2Low64 = d2.Low64;
+ uint d2High = d2.High;
+
+ if (iScale != 0)
+ {
+ iScale >>= ScaleShift;
+
+ // Scale factors are not equal. Assume that a larger scale factor (more decimal places) is likely to mean that number is smaller.
+ // Start by guessing that the right operand has the larger scale factor.
+ if (iScale < 0)
+ {
+ // Guessed scale factor wrong. Swap operands.
+ iScale = -iScale;
+ sign = -sign;
+
+ ulong tmp64 = low64;
+ low64 = d2Low64;
+ d2Low64 = tmp64;
+
+ uint tmp = high;
+ high = d2High;
+ d2High = tmp;
+ }
+
+ // d1 will need to be multiplied by 10^iScale so it will have the same scale as d2.
+ // Scaling loop, up to 10^9 at a time.
+ do
+ {
+ uint ulPwr = iScale >= MaxInt32Scale ? TenToPowerNine : s_powers10[iScale];
+ ulong tmpLow = UInt32x32To64((uint)low64, ulPwr);
+ ulong tmp = UInt32x32To64((uint)(low64 >> 32), ulPwr) + (tmpLow >> 32);
+ low64 = (uint)tmpLow + (tmp << 32);
+ tmp >>= 32;
+ tmp += UInt32x32To64(high, ulPwr);
+ // If the scaled value has more than 96 significant bits then it's greater than d2
+ if (tmp > uint.MaxValue)
+ return sign;
+ high = (uint)tmp;
+ } while ((iScale -= MaxInt32Scale) > 0);
+ }
+
+ uint cmpHigh = high - d2High;
+ if (cmpHigh != 0)
+ {
+ // check for overflow
+ if (cmpHigh > high)
+ sign = -sign;
+ return sign;
+ }
+
+ ulong cmpLow64 = low64 - d2Low64;
+ if (cmpLow64 == 0)
+ sign = 0;
+ // check for overflow
+ else if (cmpLow64 > low64)
+ sign = -sign;
+ return sign;
+ }
+
+ //**********************************************************************
+ // VarDecMul - Decimal Multiply
+ //**********************************************************************
+ internal static unsafe void VarDecMul(ref DecCalc pdecL, ref DecCalc pdecR)
+ {
+ int iScale = (byte)(pdecL.uflags + pdecR.uflags >> ScaleShift);
+
+ ulong tmp;
+ uint iHiProd;
+ Buf24 bufProd;
+ _ = &bufProd; // workaround for CS0165
+
+ if ((pdecL.High | pdecL.Mid) == 0)
+ {
+ if ((pdecR.High | pdecR.Mid) == 0)
+ {
+ // Upper 64 bits are zero.
+ //
+ ulong low64 = UInt32x32To64(pdecL.Low, pdecR.Low);
+ if (iScale > DEC_SCALE_MAX)
+ {
+ // Result iScale is too big. Divide result by power of 10 to reduce it.
+ // If the amount to divide by is > 19 the result is guaranteed
+ // less than 1/2. [max value in 64 bits = 1.84E19]
+ //
+ if (iScale > DEC_SCALE_MAX + MaxInt64Scale)
+ goto ReturnZero;
+
+ iScale -= DEC_SCALE_MAX + 1;
+ ulong ulPwr = s_ulongPowers10[iScale];
+
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ tmp = low64 / ulPwr;
+ ulong remainder = low64 - tmp * ulPwr;
+ low64 = tmp;
+
+ // Round result. See if remainder >= 1/2 of divisor.
+ // Divisor is a power of 10, so it is always even.
+ //
+ ulPwr >>= 1;
+ if (remainder >= ulPwr && (remainder > ulPwr || ((uint)low64 & 1) > 0))
+ low64++;
+
+ iScale = DEC_SCALE_MAX;
+ }
+ pdecL.Low64 = low64;
+ pdecL.uflags = ((pdecR.uflags ^ pdecL.uflags) & SignMask) | ((uint)iScale << ScaleShift);
+ return;
+ }
+ else
+ {
+ // Left value is 32-bit, result fits in 4 uints
+ tmp = UInt32x32To64(pdecL.Low, pdecR.Low);
+ bufProd.U0 = (uint)tmp;
+
+ tmp = UInt32x32To64(pdecL.Low, pdecR.Mid) + (tmp >> 32);
+ bufProd.U1 = (uint)tmp;
+ tmp >>= 32;
+
+ if (pdecR.High != 0)
+ {
+ tmp += UInt32x32To64(pdecL.Low, pdecR.High);
+ if (tmp > uint.MaxValue)
+ {
+ bufProd.Mid64 = tmp;
+ iHiProd = 3;
+ goto SkipScan;
+ }
+ }
+ if ((uint)tmp != 0)
+ {
+ bufProd.U2 = (uint)tmp;
+ iHiProd = 2;
+ goto SkipScan;
+ }
+ iHiProd = 1;
+ }
+ }
+ else if ((pdecR.High | pdecR.Mid) == 0)
+ {
+ // Right value is 32-bit, result fits in 4 uints
+ tmp = UInt32x32To64(pdecR.Low, pdecL.Low);
+ bufProd.U0 = (uint)tmp;
+
+ tmp = UInt32x32To64(pdecR.Low, pdecL.Mid) + (tmp >> 32);
+ bufProd.U1 = (uint)tmp;
+ tmp >>= 32;
+
+ if (pdecL.High != 0)
+ {
+ tmp += UInt32x32To64(pdecR.Low, pdecL.High);
+ if (tmp > uint.MaxValue)
+ {
+ bufProd.Mid64 = tmp;
+ iHiProd = 3;
+ goto SkipScan;
+ }
+ }
+ if ((uint)tmp != 0)
+ {
+ bufProd.U2 = (uint)tmp;
+ iHiProd = 2;
+ goto SkipScan;
+ }
+ iHiProd = 1;
+ }
+ else
+ {
+ // Both operands have bits set in the upper 64 bits.
+ //
+ // Compute and accumulate the 9 partial products into a
+ // 192-bit (24-byte) result.
+ //
+ // [l-h][l-m][l-l] left high, middle, low
+ // x [r-h][r-m][r-l] right high, middle, low
+ // ------------------------------
+ //
+ // [0-h][0-l] l-l * r-l
+ // [1ah][1al] l-l * r-m
+ // [1bh][1bl] l-m * r-l
+ // [2ah][2al] l-m * r-m
+ // [2bh][2bl] l-l * r-h
+ // [2ch][2cl] l-h * r-l
+ // [3ah][3al] l-m * r-h
+ // [3bh][3bl] l-h * r-m
+ // [4-h][4-l] l-h * r-h
+ // ------------------------------
+ // [p-5][p-4][p-3][p-2][p-1][p-0] prod[] array
+ //
+
+ tmp = UInt32x32To64(pdecL.Low, pdecR.Low);
+ bufProd.U0 = (uint)tmp;
+
+ ulong tmp2 = UInt32x32To64(pdecL.Low, pdecR.Mid) + (tmp >> 32);
+
+ tmp = UInt32x32To64(pdecL.Mid, pdecR.Low);
+ tmp += tmp2; // this could generate carry
+ bufProd.U1 = (uint)tmp;
+ if (tmp < tmp2) // detect carry
+ tmp2 = (tmp >> 32) | (1UL << 32);
+ else
+ tmp2 = tmp >> 32;
+
+ tmp = UInt32x32To64(pdecL.Mid, pdecR.Mid) + tmp2;
+
+ if ((pdecL.High | pdecR.High) > 0)
+ {
+ // Highest 32 bits is non-zero. Calculate 5 more partial products.
+ //
+ tmp2 = UInt32x32To64(pdecL.Low, pdecR.High);
+ tmp += tmp2; // this could generate carry
+ uint tmp3 = 0;
+ if (tmp < tmp2) // detect carry
+ tmp3 = 1;
+
+ tmp2 = UInt32x32To64(pdecL.High, pdecR.Low);
+ tmp += tmp2; // this could generate carry
+ bufProd.U2 = (uint)tmp;
+ if (tmp < tmp2) // detect carry
+ tmp3++;
+ tmp2 = ((ulong)tmp3 << 32) | (tmp >> 32);
+
+ tmp = UInt32x32To64(pdecL.Mid, pdecR.High);
+ tmp += tmp2; // this could generate carry
+ tmp3 = 0;
+ if (tmp < tmp2) // detect carry
+ tmp3 = 1;
+
+ tmp2 = UInt32x32To64(pdecL.High, pdecR.Mid);
+ tmp += tmp2; // this could generate carry
+ bufProd.U3 = (uint)tmp;
+ if (tmp < tmp2) // detect carry
+ tmp3++;
+ tmp = ((ulong)tmp3 << 32) | (tmp >> 32);
+
+ bufProd.High64 = UInt32x32To64(pdecL.High, pdecR.High) + tmp;
+
+ iHiProd = 5;
+ }
+ else if (tmp != 0)
+ {
+ bufProd.Mid64 = tmp;
+ iHiProd = 3;
+ }
+ else
+ iHiProd = 1;
+ }
+
+ // Check for leading zero ULONGs on the product
+ //
+ uint* rgulProd = (uint*)&bufProd;
+ while (rgulProd[(int)iHiProd] == 0)
+ {
+ if (iHiProd == 0)
+ goto ReturnZero;
+ iHiProd--;
+ }
+
+SkipScan:
+ if (iHiProd > 2 || iScale > DEC_SCALE_MAX)
+ {
+ iScale = ScaleResult(&bufProd, iHiProd, iScale);
+ }
+
+ pdecL.Low64 = bufProd.Low64;
+ pdecL.High = bufProd.U2;
+ pdecL.uflags = ((pdecR.uflags ^ pdecL.uflags) & SignMask) | ((uint)iScale << ScaleShift);
+ return;
+
+ReturnZero:
+ pdecL = default;
+ }
+
+ //**********************************************************************
+ // VarDecFromR4 - Convert float to Decimal
+ //**********************************************************************
+ internal static void VarDecFromR4(float input, out DecCalc pdecOut)
+ {
+ pdecOut = default;
+
+ // The most we can scale by is 10^28, which is just slightly more
+ // than 2^93. So a float with an exponent of -94 could just
+ // barely reach 0.5, but smaller exponents will always round to zero.
+ //
+ const uint SNGBIAS = 126;
+ int iExp = (int)(GetExponent(input) - SNGBIAS);
+ if (iExp < -94)
+ return; // result should be zeroed out
+
+ if (iExp > 96)
+ throw new OverflowException(SR.Overflow_Decimal);
+
+ uint flags = 0;
+ if (input < 0)
+ {
+ input = -input;
+ flags = SignMask;
+ }
+
+ // Round the input to a 7-digit integer. The R4 format has
+ // only 7 digits of precision, and we want to keep garbage digits
+ // out of the Decimal were making.
+ //
+ // Calculate max power of 10 input value could have by multiplying
+ // the exponent by log10(2). Using scaled integer multiplcation,
+ // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
+ //
+ double dbl = input;
+ int iPower = 6 - ((iExp * 19728) >> 16);
+ // iPower is between -22 and 35
+
+ if (iPower >= 0)
+ {
+ // We have less than 7 digits, scale input up.
+ //
+ if (iPower > DEC_SCALE_MAX)
+ iPower = DEC_SCALE_MAX;
+
+ dbl *= s_doublePowers10[iPower];
+ }
+ else
+ {
+ if (iPower != -1 || dbl >= 1E7)
+ dbl /= s_doublePowers10[-iPower];
+ else
+ iPower = 0; // didn't scale it
+ }
+
+ Debug.Assert(dbl < 1E7);
+ if (dbl < 1E6 && iPower < DEC_SCALE_MAX)
+ {
+ dbl *= 10;
+ iPower++;
+ Debug.Assert(dbl >= 1E6);
+ }
+
+ // Round to integer
+ //
+ uint ulMant;
+ // with SSE4.1 support ROUNDSD can be used
+ if (X86.Sse41.IsSupported)
+ ulMant = (uint)(int)Math.Round(dbl);
+ else
+ {
+ ulMant = (uint)(int)dbl;
+ dbl -= (int)ulMant; // difference between input & integer
+ if (dbl > 0.5 || dbl == 0.5 && (ulMant & 1) != 0)
+ ulMant++;
+ }
+
+ if (ulMant == 0)
+ return; // result should be zeroed out
+
+ if (iPower < 0)
+ {
+ // Add -iPower factors of 10, -iPower <= (29 - 7) = 22.
+ //
+ iPower = -iPower;
+ if (iPower < 10)
+ {
+ pdecOut.Low64 = UInt32x32To64(ulMant, s_powers10[iPower]);
+ }
+ else
+ {
+ // Have a big power of 10.
+ //
+ if (iPower > 18)
+ {
+ ulong low64 = UInt32x32To64(ulMant, s_powers10[iPower - 18]);
+ UInt64x64To128(low64, TenToPowerEighteen, ref pdecOut);
+ }
+ else
+ {
+ ulong low64 = UInt32x32To64(ulMant, s_powers10[iPower - 9]);
+ ulong hi64 = UInt32x32To64(TenToPowerNine, (uint)(low64 >> 32));
+ low64 = UInt32x32To64(TenToPowerNine, (uint)low64);
+ pdecOut.Low = (uint)low64;
+ hi64 += low64 >> 32;
+ pdecOut.Mid = (uint)hi64;
+ hi64 >>= 32;
+ pdecOut.High = (uint)hi64;
+ }
+ }
+ }
+ else
+ {
+ // Factor out powers of 10 to reduce the scale, if possible.
+ // The maximum number we could factor out would be 6. This
+ // comes from the fact we have a 7-digit number, and the
+ // MSD must be non-zero -- but the lower 6 digits could be
+ // zero. Note also the scale factor is never negative, so
+ // we can't scale by any more than the power we used to
+ // get the integer.
+ //
+ int lmax = iPower;
+ if (lmax > 6)
+ lmax = 6;
+
+ if ((ulMant & 0xF) == 0 && lmax >= 4)
+ {
+ const uint den = 10000;
+ uint div = ulMant / den;
+ if (ulMant == div * den)
+ {
+ ulMant = div;
+ iPower -= 4;
+ lmax -= 4;
+ }
+ }
+
+ if ((ulMant & 3) == 0 && lmax >= 2)
+ {
+ const uint den = 100;
+ uint div = ulMant / den;
+ if (ulMant == div * den)
+ {
+ ulMant = div;
+ iPower -= 2;
+ lmax -= 2;
+ }
+ }
+
+ if ((ulMant & 1) == 0 && lmax >= 1)
+ {
+ const uint den = 10;
+ uint div = ulMant / den;
+ if (ulMant == div * den)
+ {
+ ulMant = div;
+ iPower--;
+ }
+ }
+
+ flags |= (uint)iPower << ScaleShift;
+ pdecOut.Low = ulMant;
+ }
+
+ pdecOut.uflags = flags;
+ }
+
+ //**********************************************************************
+ // VarDecFromR8 - Convert double to Decimal
+ //**********************************************************************
+ internal static void VarDecFromR8(double input, out DecCalc pdecOut)
+ {
+ pdecOut = default;
+
+ // The most we can scale by is 10^28, which is just slightly more
+ // than 2^93. So a float with an exponent of -94 could just
+ // barely reach 0.5, but smaller exponents will always round to zero.
+ //
+ const uint DBLBIAS = 1022;
+ int iExp = (int)(GetExponent(input) - DBLBIAS);
+ if (iExp < -94)
+ return; // result should be zeroed out
+
+ if (iExp > 96)
+ throw new OverflowException(SR.Overflow_Decimal);
+
+ uint flags = 0;
+ if (input < 0)
+ {
+ input = -input;
+ flags = SignMask;
+ }
+
+ // Round the input to a 15-digit integer. The R8 format has
+ // only 15 digits of precision, and we want to keep garbage digits
+ // out of the Decimal were making.
+ //
+ // Calculate max power of 10 input value could have by multiplying
+ // the exponent by log10(2). Using scaled integer multiplcation,
+ // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
+ //
+ double dbl = input;
+ int iPower = 14 - ((iExp * 19728) >> 16);
+ // iPower is between -14 and 43
+
+ if (iPower >= 0)
+ {
+ // We have less than 15 digits, scale input up.
+ //
+ if (iPower > DEC_SCALE_MAX)
+ iPower = DEC_SCALE_MAX;
+
+ dbl *= s_doublePowers10[iPower];
+ }
+ else
+ {
+ if (iPower != -1 || dbl >= 1E15)
+ dbl /= s_doublePowers10[-iPower];
+ else
+ iPower = 0; // didn't scale it
+ }
+
+ Debug.Assert(dbl < 1E15);
+ if (dbl < 1E14 && iPower < DEC_SCALE_MAX)
+ {
+ dbl *= 10;
+ iPower++;
+ Debug.Assert(dbl >= 1E14);
+ }
+
+ // Round to int64
+ //
+ ulong ulMant;
+ // with SSE4.1 support ROUNDSD can be used
+ if (X86.Sse41.IsSupported)
+ ulMant = (ulong)(long)Math.Round(dbl);
+ else
+ {
+ ulMant = (ulong)(long)dbl;
+ dbl -= (long)ulMant; // difference between input & integer
+ if (dbl > 0.5 || dbl == 0.5 && (ulMant & 1) != 0)
+ ulMant++;
+ }
+
+ if (ulMant == 0)
+ return; // result should be zeroed out
+
+ if (iPower < 0)
+ {
+ // Add -iPower factors of 10, -iPower <= (29 - 15) = 14.
+ //
+ iPower = -iPower;
+ if (iPower < 10)
+ {
+ var pow10 = s_powers10[iPower];
+ ulong low64 = UInt32x32To64((uint)ulMant, pow10);
+ ulong hi64 = UInt32x32To64((uint)(ulMant >> 32), pow10);
+ pdecOut.Low = (uint)low64;
+ hi64 += low64 >> 32;
+ pdecOut.Mid = (uint)hi64;
+ hi64 >>= 32;
+ pdecOut.High = (uint)hi64;
+ }
+ else
+ {
+ // Have a big power of 10.
+ //
+ Debug.Assert(iPower <= 14);
+ UInt64x64To128(ulMant, s_ulongPowers10[iPower - 1], ref pdecOut);
+ }
+ }
+ else
+ {
+ // Factor out powers of 10 to reduce the scale, if possible.
+ // The maximum number we could factor out would be 14. This
+ // comes from the fact we have a 15-digit number, and the
+ // MSD must be non-zero -- but the lower 14 digits could be
+ // zero. Note also the scale factor is never negative, so
+ // we can't scale by any more than the power we used to
+ // get the integer.
+ //
+ int lmax = iPower;
+ if (lmax > 14)
+ lmax = 14;
+
+ if ((byte)ulMant == 0 && lmax >= 8)
+ {
+ const uint den = 100000000;
+ ulong div = ulMant / den;
+ if ((uint)ulMant == (uint)(div * den))
+ {
+ ulMant = div;
+ iPower -= 8;
+ lmax -= 8;
+ }
+ }
+
+ if (((uint)ulMant & 0xF) == 0 && lmax >= 4)
+ {
+ const uint den = 10000;
+ ulong div = ulMant / den;
+ if ((uint)ulMant == (uint)(div * den))
+ {
+ ulMant = div;
+ iPower -= 4;
+ lmax -= 4;
+ }
+ }
+
+ if (((uint)ulMant & 3) == 0 && lmax >= 2)
+ {
+ const uint den = 100;
+ ulong div = ulMant / den;
+ if ((uint)ulMant == (uint)(div * den))
+ {
+ ulMant = div;
+ iPower -= 2;
+ lmax -= 2;
+ }
+ }
+
+ if (((uint)ulMant & 1) == 0 && lmax >= 1)
+ {
+ const uint den = 10;
+ ulong div = ulMant / den;
+ if ((uint)ulMant == (uint)(div * den))
+ {
+ ulMant = div;
+ iPower--;
+ }
+ }
+
+ flags |= (uint)iPower << ScaleShift;
+ pdecOut.Low64 = ulMant;
+ }
+
+ pdecOut.uflags = flags;
+ }
+
+ //**********************************************************************
+ // VarR4ToDec - Convert Decimal to float
+ //**********************************************************************
+ internal static float VarR4FromDec(ref decimal pdecIn)
+ {
+ return (float)VarR8FromDec(ref pdecIn);
+ }
+
+ //**********************************************************************
+ // VarR8ToDec - Convert Decimal to double
+ //**********************************************************************
+ internal static double VarR8FromDec(ref decimal pdecIn)
+ {
+ // Value taken via reverse engineering the double that corresponds to 2^64. (oleaut32 has ds2to64 = DEFDS(0, 0, DBLBIAS + 65, 0))
+ const double ds2to64 = 1.8446744073709552e+019;
+
+ double dbl = ((double)pdecIn.Low64 +
+ (double)pdecIn.High * ds2to64) / s_doublePowers10[pdecIn.Scale];
+
+ if (pdecIn.IsNegative)
+ dbl = -dbl;
+
+ return dbl;
+ }
+
+ internal static int GetHashCode(in decimal d)
+ {
+ if ((d.Low | d.Mid | d.High) == 0)
+ return 0;
+
+ uint flags = (uint)d.flags;
+ if ((flags & ScaleMask) == 0 || (d.Low & 1) != 0)
+ return (int)(flags ^ d.High ^ d.Mid ^ d.Low);
+
+ int scale = (byte)(flags >> ScaleShift);
+ uint low = d.Low;
+ ulong high64 = ((ulong)d.High << 32) | d.Mid;
+
+ Unscale(ref low, ref high64, ref scale);
+
+ flags = ((flags) & ~ScaleMask) | (uint)scale << ScaleShift;
+ return (int)(flags ^ (uint)(high64 >> 32) ^ (uint)high64 ^ low);
+ }
+
+ // VarDecDiv divides two decimal values. On return, d1 contains the result
+ // of the operation.
+ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2)
+ {
+ Buf12 bufQuo, bufDivisor;
+ _ = &bufQuo; // workaround for CS0165
+ _ = &bufDivisor; // workaround for CS0165
+ uint ulPwr;
+ int iCurScale;
+
+ int iScale = (sbyte)(d1.uflags - d2.uflags >> ScaleShift);
+ bool fUnscale = false;
+ uint ulTmp;
+
+ if (d2.High == 0 && d2.Mid == 0)
+ {
+ // Divisor is only 32 bits. Easy divide.
+ //
+ uint den = d2.Low;
+ if (den == 0)
+ throw new DivideByZeroException();
+
+ bufQuo.Low64 = d1.Low64;
+ bufQuo.U2 = d1.High;
+ uint remainder = Div96By32(ref bufQuo, den);
+
+ for (;;)
+ {
+ if (remainder == 0)
+ {
+ if (iScale < 0)
+ {
+ iCurScale = Math.Min(9, -iScale);
+ goto HaveScale;
+ }
+ break;
+ }
+
+ // We need to unscale if and only if we have a non-zero remainder
+ fUnscale = true;
+
+ // We have computed a quotient based on the natural scale
+ // ( <dividend scale> - <divisor scale> ). We have a non-zero
+ // remainder, so now we should increase the scale if possible to
+ // include more quotient bits.
+ //
+ // If it doesn't cause overflow, we'll loop scaling by 10^9 and
+ // computing more quotient bits as long as the remainder stays
+ // non-zero. If scaling by that much would cause overflow, we'll
+ // drop out of the loop and scale by as much as we can.
+ //
+ // Scaling by 10^9 will overflow if rgulQuo[2].rgulQuo[1] >= 2^32 / 10^9
+ // = 4.294 967 296. So the upper limit is rgulQuo[2] == 4 and
+ // rgulQuo[1] == 0.294 967 296 * 2^32 = 1,266,874,889.7+. Since
+ // quotient bits in rgulQuo[0] could be all 1's, then 1,266,874,888
+ // is the largest value in rgulQuo[1] (when rgulQuo[2] == 4) that is
+ // assured not to overflow.
+ //
+ if (iScale == DEC_SCALE_MAX || (iCurScale = SearchScale(ref bufQuo, iScale)) == 0)
+ {
+ // No more scaling to be done, but remainder is non-zero.
+ // Round quotient.
+ //
+ ulTmp = remainder << 1;
+ if (ulTmp < remainder || ulTmp >= den && (ulTmp > den || (bufQuo.U0 & 1) != 0))
+ goto RoundUp;
+ break;
+ }
+
+ HaveScale:
+ ulPwr = s_powers10[iCurScale];
+ iScale += iCurScale;
+
+ if (IncreaseScale(ref bufQuo, ulPwr) != 0)
+ goto ThrowOverflow;
+
+ ulong num = UInt32x32To64(remainder, ulPwr);
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ uint div = (uint)(num / den);
+ remainder = (uint)num - div * den;
+
+ if (!Add32To96(ref bufQuo, div))
+ {
+ iScale = OverflowUnscale(ref bufQuo, iScale, remainder != 0);
+ break;
+ }
+ } // for (;;)
+ }
+ else
+ {
+ // Divisor has bits set in the upper 64 bits.
+ //
+ // Divisor must be fully normalized (shifted so bit 31 of the most
+ // significant ULONG is 1). Locate the MSB so we know how much to
+ // normalize by. The dividend will be shifted by the same amount so
+ // the quotient is not changed.
+ //
+ bufDivisor.Low64 = d2.Low64;
+ ulTmp = d2.High;
+ bufDivisor.U2 = ulTmp;
+ if (ulTmp == 0)
+ ulTmp = d2.Mid;
+
+ iCurScale = X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(ulTmp) : LeadingZeroCount(ulTmp);
+
+ // Shift both dividend and divisor left by iCurScale.
+ //
+ Buf16 bufRem;
+ _ = &bufRem; // workaround for CS0165
+ bufRem.Low64 = d1.Low64 << iCurScale;
+ bufRem.High64 = (d1.Mid + ((ulong)d1.High << 32)) >> (31 - iCurScale) >> 1;
+
+ ulong divisor = bufDivisor.Low64 << iCurScale;
+
+ if (bufDivisor.U2 == 0)
+ {
+ // Have a 64-bit divisor in sdlDivisor. The remainder
+ // (currently 96 bits spread over 4 ULONGs) will be < divisor.
+ //
+
+ bufQuo.U1 = Div96By64(ref *(Buf12*)&bufRem.U1, divisor);
+ bufQuo.U0 = Div96By64(ref *(Buf12*)&bufRem, divisor);
+
+ for (;;)
+ {
+ if (bufRem.Low64 == 0)
+ {
+ if (iScale < 0)
+ {
+ iCurScale = Math.Min(9, -iScale);
+ goto HaveScale64;
+ }
+ break;
+ }
+
+ // We need to unscale if and only if we have a non-zero remainder
+ fUnscale = true;
+
+ // Remainder is non-zero. Scale up quotient and remainder by
+ // powers of 10 so we can compute more significant bits.
+ //
+ if (iScale == DEC_SCALE_MAX || (iCurScale = SearchScale(ref bufQuo, iScale)) == 0)
+ {
+ // No more scaling to be done, but remainder is non-zero.
+ // Round quotient.
+ //
+ ulong tmp = bufRem.Low64;
+ if ((long)tmp < 0 || (tmp <<= 1) > divisor ||
+ (tmp == divisor && (bufQuo.U0 & 1) != 0))
+ goto RoundUp;
+ break;
+ }
+
+ HaveScale64:
+ ulPwr = s_powers10[iCurScale];
+ iScale += iCurScale;
+
+ if (IncreaseScale(ref bufQuo, ulPwr) != 0)
+ goto ThrowOverflow;
+
+ IncreaseScale64(ref *(Buf12*)&bufRem, ulPwr);
+ ulTmp = Div96By64(ref *(Buf12*)&bufRem, divisor);
+ if (!Add32To96(ref bufQuo, ulTmp))
+ {
+ iScale = OverflowUnscale(ref bufQuo, iScale, bufRem.Low64 != 0);
+ break;
+ }
+ } // for (;;)
+ }
+ else
+ {
+ // Have a 96-bit divisor in rgulDivisor[].
+ //
+ // Start by finishing the shift left by iCurScale.
+ //
+ uint tmp = (uint)(bufDivisor.High64 >> (31 - iCurScale) >> 1);
+ bufDivisor.Low64 = divisor;
+ bufDivisor.U2 = tmp;
+
+ // The remainder (currently 96 bits spread over 4 ULONGs)
+ // will be < divisor.
+ //
+ bufQuo.Low64 = Div128By96(ref bufRem, ref bufDivisor);
+
+ for (;;)
+ {
+ if ((bufRem.Low64 | bufRem.U2) == 0)
+ {
+ if (iScale < 0)
+ {
+ iCurScale = Math.Min(9, -iScale);
+ goto HaveScale96;
+ }
+ break;
+ }
+
+ // We need to unscale if and only if we have a non-zero remainder
+ fUnscale = true;
+
+ // Remainder is non-zero. Scale up quotient and remainder by
+ // powers of 10 so we can compute more significant bits.
+ //
+ if (iScale == DEC_SCALE_MAX || (iCurScale = SearchScale(ref bufQuo, iScale)) == 0)
+ {
+ // No more scaling to be done, but remainder is non-zero.
+ // Round quotient.
+ //
+ if ((int)bufRem.U2 < 0)
+ {
+ goto RoundUp;
+ }
+
+ ulTmp = bufRem.U1 >> 31;
+ bufRem.Low64 <<= 1;
+ bufRem.U2 = (bufRem.U2 << 1) + ulTmp;
+
+ if (bufRem.U2 > bufDivisor.U2 || bufRem.U2 == bufDivisor.U2 &&
+ (bufRem.Low64 > bufDivisor.Low64 || bufRem.Low64 == bufDivisor.Low64 &&
+ (bufQuo.U0 & 1) != 0))
+ goto RoundUp;
+ break;
+ }
+
+ HaveScale96:
+ ulPwr = s_powers10[iCurScale];
+ iScale += iCurScale;
+
+ if (IncreaseScale(ref bufQuo, ulPwr) != 0)
+ goto ThrowOverflow;
+
+ bufRem.U3 = IncreaseScale(ref *(Buf12*)&bufRem, ulPwr);
+ ulTmp = Div128By96(ref bufRem, ref bufDivisor);
+ if (!Add32To96(ref bufQuo, ulTmp))
+ {
+ iScale = OverflowUnscale(ref bufQuo, iScale, (bufRem.Low64 | bufRem.High64) != 0);
+ break;
+ }
+ } // for (;;)
+ }
+ }
+
+Unscale:
+ if (fUnscale)
+ {
+ uint low = bufQuo.U0;
+ ulong high64 = bufQuo.High64;
+ Unscale(ref low, ref high64, ref iScale);
+ d1.Low = low;
+ d1.Mid = (uint)high64;
+ d1.High = (uint)(high64 >> 32);
+ }
+ else
+ {
+ d1.Low64 = bufQuo.Low64;
+ d1.High = bufQuo.U2;
+ }
+
+ d1.uflags = ((d1.uflags ^ d2.uflags) & SignMask) | ((uint)iScale << ScaleShift);
+ return;
+
+RoundUp:
+ {
+ if (++bufQuo.Low64 == 0 && ++bufQuo.U2 == 0)
+ {
+ iScale = OverflowUnscale(ref bufQuo, iScale, true);
+ }
+ goto Unscale;
+ }
+
+ThrowOverflow:
+ throw new OverflowException(SR.Overflow_Decimal);
+ }
+
+ //**********************************************************************
+ // VarDecMod - Computes the remainder between two decimals
+ //**********************************************************************
+ internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2)
+ {
+ if ((d2.ulo | d2.umid | d2.uhi) == 0)
+ throw new DivideByZeroException();
+
+ if ((d1.ulo | d1.umid | d1.uhi) == 0)
+ return;
+
+ // In the operation x % y the sign of y does not matter. Result will have the sign of x.
+ d2.uflags = (d2.uflags & ~SignMask) | (d1.uflags & SignMask);
+
+ int cmp = VarDecCmpSub(in Unsafe.As<DecCalc, decimal>(ref d1), in Unsafe.As<DecCalc, decimal>(ref d2));
+ if (cmp == 0)
+ {
+ d1.ulo = 0;
+ d1.umid = 0;
+ d1.uhi = 0;
+ if (d2.uflags > d1.uflags)
+ d1.uflags = d2.uflags;
+ return;
+ }
+ if ((cmp ^ (int)(d1.uflags & SignMask)) < 0)
+ return;
+
+ // This piece of code is to work around the fact that Dividing a decimal with 28 digits number by decimal which causes
+ // causes the result to be 28 digits, can cause to be incorrectly rounded up.
+ // eg. Decimal.MaxValue / 2 * Decimal.MaxValue will overflow since the division by 2 was rounded instead of being truncked.
+ DecCalc tmp = d2;
+ DecAddSub(ref d1, ref tmp, true);
+
+ // Formula: d1 - (RoundTowardsZero(d1 / d2) * d2)
+ tmp = d1;
+ VarDecDiv(ref tmp, ref d2);
+ Truncate(ref Unsafe.As<DecCalc, decimal>(ref tmp));
+ VarDecMul(ref tmp, ref d2);
+ uint flags = d1.uflags;
+ DecAddSub(ref d1, ref tmp, true);
+ // See if the result has crossed 0
+ if (((flags ^ d1.uflags) & SignMask) != 0)
+ {
+ if ((d1.Low | d1.Mid | d1.High) == 0 || d1.Scale == DEC_SCALE_MAX && d1.Low64 == 1 && d1.High == 0)
+ {
+ // Certain Remainder operations on decimals with 28 significant digits round
+ // to [+-]0.0000000000000000000000000001m instead of [+-]0m during the intermediate calculations.
+ // 'zero' results just need their sign corrected.
+ d1.uflags ^= SignMask;
+ }
+ else
+ {
+ // If the division rounds up because it runs out of digits, the multiplied result can end up with a larger
+ // absolute value and the result of the formula crosses 0. To correct it can add the divisor back.
+ DecAddSub(ref d1, ref d2, false);
+ }
+ }
+ }
+
+ internal enum RoundingMode
+ {
+ ToEven = 0,
+ AwayFromZero = 1,
+ Truncate = 2,
+ Floor = 3,
+ Ceiling = 4,
+ }
+
+ // Does an in-place round by the specified scale
+ internal static void InternalRound(ref DecCalc d, uint scale, RoundingMode mode)
+ {
+ // the scale becomes the desired decimal count
+ d.uflags -= scale << ScaleShift;
+
+ uint remainder, sticky = 0, power;
+ // First divide the value by constant 10^9 up to three times
+ while (scale >= MaxInt32Scale)
+ {
+ scale -= MaxInt32Scale;
+
+ const uint divisor = TenToPowerNine;
+ uint n = d.uhi;
+ if (n == 0)
+ {
+ ulong tmp = d.Low64;
+ ulong div = tmp / divisor;
+ d.Low64 = div;
+ remainder = (uint)(tmp - div * divisor);
+ }
+ else
+ {
+ uint q;
+ d.uhi = q = n / divisor;
+ remainder = n - q * divisor;
+ n = d.umid;
+ if ((n | remainder) != 0)
+ {
+ d.umid = q = (uint)((((ulong)remainder << 32) | n) / divisor);
+ remainder = n - q * divisor;
+ }
+ n = d.ulo;
+ if ((n | remainder) != 0)
+ {
+ d.ulo = q = (uint)((((ulong)remainder << 32) | n) / divisor);
+ remainder = n - q * divisor;
+ }
+ }
+ power = divisor;
+ if (scale == 0)
+ goto checkRemainder;
+ sticky |= remainder;
+ }
+
+ {
+ power = s_powers10[scale];
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ uint n = d.uhi;
+ if (n == 0)
+ {
+ ulong tmp = d.Low64;
+ if (tmp == 0)
+ {
+ if (mode <= RoundingMode.Truncate)
+ goto done;
+ remainder = 0;
+ goto checkRemainder;
+ }
+ ulong div = tmp / power;
+ d.Low64 = div;
+ remainder = (uint)(tmp - div * power);
+ }
+ else
+ {
+ uint q;
+ d.uhi = q = n / power;
+ remainder = n - q * power;
+ n = d.umid;
+ if ((n | remainder) != 0)
+ {
+ d.umid = q = (uint)((((ulong)remainder << 32) | n) / power);
+ remainder = n - q * power;
+ }
+ n = d.ulo;
+ if ((n | remainder) != 0)
+ {
+ d.ulo = q = (uint)((((ulong)remainder << 32) | n) / power);
+ remainder = n - q * power;
+ }
+ }
+ }
+
+checkRemainder:
+ if (mode == RoundingMode.Truncate)
+ goto done;
+ else if (mode == RoundingMode.ToEven)
+ {
+ // To do IEEE rounding, we add LSB of result to sticky bits so either causes round up if remainder * 2 == last divisor.
+ remainder <<= 1;
+ if ((sticky | d.ulo & 1) != 0)
+ remainder++;
+ if (power >= remainder)
+ goto done;
+ }
+ else if (mode == RoundingMode.AwayFromZero)
+ {
+ // Round away from zero at the mid point.
+ remainder <<= 1;
+ if (power > remainder)
+ goto done;
+ }
+ else if (mode == RoundingMode.Floor)
+ {
+ // Round toward -infinity if we have chopped off a non-zero amount from a negative value.
+ if ((remainder | sticky) == 0 || !d.IsNegative)
+ goto done;
+ }
+ else
+ {
+ Debug.Assert(mode == RoundingMode.Ceiling);
+ // Round toward infinity if we have chopped off a non-zero amount from a positive value.
+ if ((remainder | sticky) == 0 || d.IsNegative)
+ goto done;
+ }
+ if (++d.Low64 == 0)
+ d.uhi++;
+done:
+ return;
+ }
+
+ internal static uint DecDivMod1E9(ref DecCalc value)
+ {
+ ulong high64 = ((ulong)value.uhi << 32) + value.umid;
+ ulong div64 = high64 / TenToPowerNine;
+ value.uhi = (uint)(div64 >> 32);
+ value.umid = (uint)div64;
+
+ ulong num = ((high64 - (uint)div64 * TenToPowerNine) << 32) + value.ulo;
+ uint div = (uint)(num / TenToPowerNine);
+ value.ulo = div;
+ return (uint)num - div * TenToPowerNine;
+ }
+
+ struct PowerOvfl
+ {
+ public readonly uint Hi;
+ public readonly ulong MidLo;
+
+ public PowerOvfl(uint hi, uint mid, uint lo)
+ {
+ Hi = hi;
+ MidLo = ((ulong)mid << 32) + lo;
+ }
+ }
+
+ static readonly PowerOvfl[] PowerOvflValues = new[]
+ {
+ // This is a table of the largest values that can be in the upper two
+ // ULONGs of a 96-bit number that will not overflow when multiplied
+ // by a given power. For the upper word, this is a table of
+ // 2^32 / 10^n for 1 <= n <= 8. For the lower word, this is the
+ // remaining fraction part * 2^32. 2^32 = 4294967296.
+ //
+ new PowerOvfl(429496729, 2576980377, 2576980377), // 10^1 remainder 0.6
+ new PowerOvfl(42949672, 4123168604, 687194767), // 10^2 remainder 0.16
+ new PowerOvfl(4294967, 1271310319, 2645699854), // 10^3 remainder 0.616
+ new PowerOvfl(429496, 3133608139, 694066715), // 10^4 remainder 0.1616
+ new PowerOvfl(42949, 2890341191, 2216890319), // 10^5 remainder 0.51616
+ new PowerOvfl(4294, 4154504685, 2369172679), // 10^6 remainder 0.551616
+ new PowerOvfl(429, 2133437386, 4102387834), // 10^7 remainder 0.9551616
+ new PowerOvfl(42, 4078814305, 410238783), // 10^8 remainder 0.09991616
+ };
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct Buf12
+ {
+ [FieldOffset(0 * 4)]
+ public uint U0;
+ [FieldOffset(1 * 4)]
+ public uint U1;
+ [FieldOffset(2 * 4)]
+ public uint U2;
+
+ [FieldOffset(0)]
+ private ulong ulo64LE;
+ [FieldOffset(4)]
+ private ulong uhigh64LE;
+
+ public ulong Low64
+ {
+#if BIGENDIAN
+ get => ((ulong)U1 << 32) | U0;
+ set { U1 = (uint)(value >> 32); U0 = (uint)value; }
+#else
+ get => ulo64LE;
+ set => ulo64LE = value;
+#endif
+ }
+
+ /// <summary>
+ /// U1-U2 combined (overlaps with Low64)
+ /// </summary>
+ public ulong High64
+ {
+#if BIGENDIAN
+ get => ((ulong)U2 << 32) | U1;
+ set { U2 = (uint)(value >> 32); U1 = (uint)value; }
+#else
+ get => uhigh64LE;
+ set => uhigh64LE = value;
+#endif
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct Buf16
+ {
+ [FieldOffset(0 * 4)]
+ public uint U0;
+ [FieldOffset(1 * 4)]
+ public uint U1;
+ [FieldOffset(2 * 4)]
+ public uint U2;
+ [FieldOffset(3 * 4)]
+ public uint U3;
+
+ [FieldOffset(0 * 8)]
+ private ulong ulo64LE;
+ [FieldOffset(1 * 8)]
+ private ulong uhigh64LE;
+
+ public ulong Low64
+ {
+#if BIGENDIAN
+ get => ((ulong)U1 << 32) | U0;
+ set { U1 = (uint)(value >> 32); U0 = (uint)value; }
+#else
+ get => ulo64LE;
+ set => ulo64LE = value;
+#endif
+ }
+
+ public ulong High64
+ {
+#if BIGENDIAN
+ get => ((ulong)U3 << 32) | U2;
+ set { U3 = (uint)(value >> 32); U2 = (uint)value; }
+#else
+ get => uhigh64LE;
+ set => uhigh64LE = value;
+#endif
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct Buf24
+ {
+ [FieldOffset(0 * 4)]
+ public uint U0;
+ [FieldOffset(1 * 4)]
+ public uint U1;
+ [FieldOffset(2 * 4)]
+ public uint U2;
+ [FieldOffset(3 * 4)]
+ public uint U3;
+ [FieldOffset(4 * 4)]
+ public uint U4;
+ [FieldOffset(5 * 4)]
+ public uint U5;
+
+ [FieldOffset(0 * 8)]
+ private ulong ulo64LE;
+ [FieldOffset(1 * 8)]
+ private ulong umid64LE;
+ [FieldOffset(2 * 8)]
+ private ulong uhigh64LE;
+
+ public ulong Low64
+ {
+#if BIGENDIAN
+ get => ((ulong)U1 << 32) | U0;
+ set { U1 = (uint)(value >> 32); U0 = (uint)value; }
+#else
+ get => ulo64LE;
+ set => ulo64LE = value;
+#endif
+ }
+
+ public ulong Mid64
+ {
+#if BIGENDIAN
+ get => ((ulong)U3 << 32) | U2;
+ set { U3 = (uint)(value >> 32); U2 = (uint)value; }
+#else
+ get => umid64LE;
+ set => umid64LE = value;
+#endif
+ }
+
+ public ulong High64
+ {
+#if BIGENDIAN
+ get => ((ulong)U5 << 32) | U4;
+ set { U5 = (uint)(value >> 32); U4 = (uint)value; }
+#else
+ get => uhigh64LE;
+ set => uhigh64LE = value;
+#endif
+ }
+
+ public int Length => 6;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Decimal.cs b/src/System.Private.CoreLib/shared/System/Decimal.cs
new file mode 100644
index 000000000..7e472b70c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Decimal.cs
@@ -0,0 +1,1121 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+
+namespace System
+{
+ // Implements the Decimal data type. The Decimal data type can
+ // represent values ranging from -79,228,162,514,264,337,593,543,950,335 to
+ // 79,228,162,514,264,337,593,543,950,335 with 28 significant digits. The
+ // Decimal data type is ideally suited to financial calculations that
+ // require a large number of significant digits and no round-off errors.
+ //
+ // The finite set of values of type Decimal are of the form m
+ // / 10e, where m is an integer such that
+ // -296 <; m <; 296, and e is an integer
+ // between 0 and 28 inclusive.
+ //
+ // Contrary to the float and double data types, decimal
+ // fractional numbers such as 0.1 can be represented exactly in the
+ // Decimal representation. In the float and double
+ // representations, such numbers are often infinite fractions, making those
+ // representations more prone to round-off errors.
+ //
+ // The Decimal class implements widening conversions from the
+ // ubyte, char, short, int, and long types
+ // to Decimal. These widening conversions never loose any information
+ // and never throw exceptions. The Decimal class also implements
+ // narrowing conversions from Decimal to ubyte, char,
+ // short, int, and long. These narrowing conversions round
+ // the Decimal value towards zero to the nearest integer, and then
+ // converts that integer to the destination type. An OverflowException
+ // is thrown if the result is not within the range of the destination type.
+ //
+ // The Decimal class provides a widening conversion from
+ // Currency to Decimal. This widening conversion never loses any
+ // information and never throws exceptions. The Currency class provides
+ // a narrowing conversion from Decimal to Currency. This
+ // narrowing conversion rounds the Decimal to four decimals and then
+ // converts that number to a Currency. An OverflowException
+ // is thrown if the result is not within the range of the Currency type.
+ //
+ // The Decimal class provides narrowing conversions to and from the
+ // float and double types. A conversion from Decimal to
+ // float or double may loose precision, but will not loose
+ // information about the overall magnitude of the numeric value, and will never
+ // throw an exception. A conversion from float or double to
+ // Decimal throws an OverflowException if the value is not within
+ // the range of the Decimal type.
+ [StructLayout(LayoutKind.Sequential)]
+ [Serializable]
+ [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+#if !MONO
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public readonly partial struct Decimal : IFormattable, IComparable, IConvertible, IComparable<decimal>, IEquatable<decimal>, IDeserializationCallback, ISpanFormattable
+ {
+ // Sign mask for the flags field. A value of zero in this bit indicates a
+ // positive Decimal value, and a value of one in this bit indicates a
+ // negative Decimal value.
+ //
+ // Look at OleAut's DECIMAL_NEG constant to check for negative values
+ // in native code.
+ private const int SignMask = unchecked((int)0x80000000);
+
+ // Scale mask for the flags field. This byte in the flags field contains
+ // the power of 10 to divide the Decimal value by. The scale byte must
+ // contain a value between 0 and 28 inclusive.
+ private const int ScaleMask = 0x00FF0000;
+
+ // Number of bits scale is shifted by.
+ private const int ScaleShift = 16;
+
+ // Constant representing the Decimal value 0.
+ public const decimal Zero = 0m;
+
+ // Constant representing the Decimal value 1.
+ public const decimal One = 1m;
+
+ // Constant representing the Decimal value -1.
+ public const decimal MinusOne = -1m;
+
+ // Constant representing the largest possible Decimal value. The value of
+ // this constant is 79,228,162,514,264,337,593,543,950,335.
+ public const decimal MaxValue = 79228162514264337593543950335m;
+
+ // Constant representing the smallest possible Decimal value. The value of
+ // this constant is -79,228,162,514,264,337,593,543,950,335.
+ public const decimal MinValue = -79228162514264337593543950335m;
+
+ // The lo, mid, hi, and flags fields contain the representation of the
+ // Decimal value. The lo, mid, and hi fields contain the 96-bit integer
+ // part of the Decimal. Bits 0-15 (the lower word) of the flags field are
+ // unused and must be zero; bits 16-23 contain must contain a value between
+ // 0 and 28, indicating the power of 10 to divide the 96-bit integer part
+ // by to produce the Decimal value; bits 24-30 are unused and must be zero;
+ // and finally bit 31 indicates the sign of the Decimal value, 0 meaning
+ // positive and 1 meaning negative.
+ //
+ // NOTE: Do not change the order in which these fields are declared. The
+ // native methods in this class rely on this particular order.
+ // Do not rename (binary serialization).
+ private readonly int flags;
+ private readonly int hi;
+ private readonly int lo;
+ private readonly int mid;
+
+ // Constructs a Decimal from an integer value.
+ //
+ public Decimal(int value)
+ {
+ if (value >= 0)
+ {
+ flags = 0;
+ }
+ else
+ {
+ flags = SignMask;
+ value = -value;
+ }
+ lo = value;
+ mid = 0;
+ hi = 0;
+ }
+
+ // Constructs a Decimal from an unsigned integer value.
+ //
+ [CLSCompliant(false)]
+ public Decimal(uint value)
+ {
+ flags = 0;
+ lo = (int)value;
+ mid = 0;
+ hi = 0;
+ }
+
+ // Constructs a Decimal from a long value.
+ //
+ public Decimal(long value)
+ {
+ if (value >= 0)
+ {
+ flags = 0;
+ }
+ else
+ {
+ flags = SignMask;
+ value = -value;
+ }
+ lo = (int)value;
+ mid = (int)(value >> 32);
+ hi = 0;
+ }
+
+ // Constructs a Decimal from an unsigned long value.
+ //
+ [CLSCompliant(false)]
+ public Decimal(ulong value)
+ {
+ flags = 0;
+ lo = (int)value;
+ mid = (int)(value >> 32);
+ hi = 0;
+ }
+
+ // Constructs a Decimal from a float value.
+ //
+ public Decimal(float value)
+ {
+ DecCalc.VarDecFromR4(value, out AsMutable(ref this));
+ }
+
+ // Constructs a Decimal from a double value.
+ //
+ public Decimal(double value)
+ {
+ DecCalc.VarDecFromR8(value, out AsMutable(ref this));
+ }
+
+ //
+ // Decimal <==> Currency conversion.
+ //
+ // A Currency represents a positive or negative decimal value with 4 digits past the decimal point. The actual Int64 representation used by these methods
+ // is the currency value multiplied by 10,000. For example, a currency value of $12.99 would be represented by the Int64 value 129,900.
+ //
+ public static decimal FromOACurrency(long cy)
+ {
+ ulong absoluteCy; // has to be ulong to accommodate the case where cy == long.MinValue.
+ bool isNegative = false;
+ if (cy < 0)
+ {
+ isNegative = true;
+ absoluteCy = (ulong)(-cy);
+ }
+ else
+ {
+ absoluteCy = (ulong)cy;
+ }
+
+ // In most cases, FromOACurrency() produces a Decimal with Scale set to 4. Unless, that is, some of the trailing digits past the decimal point are zero,
+ // in which case, for compatibility with .Net, we reduce the Scale by the number of zeros. While the result is still numerically equivalent, the scale does
+ // affect the ToString() value. In particular, it prevents a converted currency value of $12.95 from printing uglily as "12.9500".
+ int scale = 4;
+ if (absoluteCy != 0) // For compatibility, a currency of 0 emits the Decimal "0.0000" (scale set to 4).
+ {
+ while (scale != 0 && ((absoluteCy % 10) == 0))
+ {
+ scale--;
+ absoluteCy /= 10;
+ }
+ }
+
+ return new decimal((int)absoluteCy, (int)(absoluteCy >> 32), 0, isNegative, (byte)scale);
+ }
+
+ public static long ToOACurrency(decimal value)
+ {
+ return DecCalc.VarCyFromDec(ref AsMutable(ref value));
+ }
+
+ private static bool IsValid(int flags) => (flags & ~(SignMask | ScaleMask)) == 0 && ((uint)(flags & ScaleMask) <= (28 << ScaleShift));
+
+ // Constructs a Decimal from an integer array containing a binary
+ // representation. The bits argument must be a non-null integer
+ // array with four elements. bits[0], bits[1], and
+ // bits[2] contain the low, middle, and high 32 bits of the 96-bit
+ // integer part of the Decimal. bits[3] contains the scale factor
+ // and sign of the Decimal: bits 0-15 (the lower word) are unused and must
+ // be zero; bits 16-23 must contain a value between 0 and 28, indicating
+ // the power of 10 to divide the 96-bit integer part by to produce the
+ // Decimal value; bits 24-30 are unused and must be zero; and finally bit
+ // 31 indicates the sign of the Decimal value, 0 meaning positive and 1
+ // meaning negative.
+ //
+ // Note that there are several possible binary representations for the
+ // same numeric value. For example, the value 1 can be represented as {1,
+ // 0, 0, 0} (integer value 1 with a scale factor of 0) and equally well as
+ // {1000, 0, 0, 0x30000} (integer value 1000 with a scale factor of 3).
+ // The possible binary representations of a particular value are all
+ // equally valid, and all are numerically equivalent.
+ //
+ public Decimal(int[] bits)
+ {
+ if (bits == null)
+ throw new ArgumentNullException(nameof(bits));
+ if (bits.Length == 4)
+ {
+ int f = bits[3];
+ if (IsValid(f))
+ {
+ lo = bits[0];
+ mid = bits[1];
+ hi = bits[2];
+ flags = f;
+ return;
+ }
+ }
+ throw new ArgumentException(SR.Arg_DecBitCtor);
+ }
+
+ // Constructs a Decimal from its constituent parts.
+ //
+ public Decimal(int lo, int mid, int hi, bool isNegative, byte scale)
+ {
+ if (scale > 28)
+ throw new ArgumentOutOfRangeException(nameof(scale), SR.ArgumentOutOfRange_DecimalScale);
+ this.lo = lo;
+ this.mid = mid;
+ this.hi = hi;
+ flags = ((int)scale) << 16;
+ if (isNegative)
+ flags |= SignMask;
+ }
+
+ void IDeserializationCallback.OnDeserialization(object sender)
+ {
+ // OnDeserialization is called after each instance of this class is deserialized.
+ // This callback method performs decimal validation after being deserialized.
+ if (!IsValid(flags))
+ throw new SerializationException(SR.Overflow_Decimal);
+ }
+
+ // Constructs a Decimal from its constituent parts.
+ private Decimal(int lo, int mid, int hi, int flags)
+ {
+ if (IsValid(flags))
+ {
+ this.lo = lo;
+ this.mid = mid;
+ this.hi = hi;
+ this.flags = flags;
+ return;
+ }
+ throw new ArgumentException(SR.Arg_DecBitCtor);
+ }
+
+ private Decimal(in decimal d, int flags)
+ {
+ this = d;
+ this.flags = flags;
+ }
+
+ // Returns the absolute value of the given Decimal. If d is
+ // positive, the result is d. If d is negative, the result
+ // is -d.
+ //
+ internal static decimal Abs(ref decimal d)
+ {
+ return new decimal(in d, d.flags & ~SignMask);
+ }
+
+ // Adds two Decimal values.
+ //
+ public static decimal Add(decimal d1, decimal d2)
+ {
+ DecCalc.DecAddSub(ref AsMutable(ref d1), ref AsMutable(ref d2), false);
+ return d1;
+ }
+
+
+ // Rounds a Decimal to an integer value. The Decimal argument is rounded
+ // towards positive infinity.
+ public static decimal Ceiling(decimal d)
+ {
+ int flags = d.flags;
+ if ((flags & ScaleMask) != 0)
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Ceiling);
+ return d;
+ }
+
+ // Compares two Decimal values, returning an integer that indicates their
+ // relationship.
+ //
+ public static int Compare(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2);
+ }
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Decimal, this method throws an ArgumentException.
+ //
+ public int CompareTo(object value)
+ {
+ if (value == null)
+ return 1;
+ if (!(value is decimal))
+ throw new ArgumentException(SR.Arg_MustBeDecimal);
+
+ decimal other = (decimal)value;
+ return DecCalc.VarDecCmp(in this, in other);
+ }
+
+ public int CompareTo(decimal value)
+ {
+ return DecCalc.VarDecCmp(in this, in value);
+ }
+
+ // Divides two Decimal values.
+ //
+ public static decimal Divide(decimal d1, decimal d2)
+ {
+ DecCalc.VarDecDiv(ref AsMutable(ref d1), ref AsMutable(ref d2));
+ return d1;
+ }
+
+ // Checks if this Decimal is equal to a given object. Returns true
+ // if the given object is a boxed Decimal and its value is equal to the
+ // value of this Decimal. Returns false otherwise.
+ //
+ public override bool Equals(object value)
+ {
+ if (value is decimal)
+ {
+ decimal other = (decimal)value;
+ return DecCalc.VarDecCmp(in this, in other) == 0;
+ }
+ return false;
+ }
+
+ public bool Equals(decimal value)
+ {
+ return DecCalc.VarDecCmp(in this, in value) == 0;
+ }
+
+ // Returns the hash code for this Decimal.
+ //
+ public override int GetHashCode() => DecCalc.GetHashCode(in this);
+
+ // Compares two Decimal values for equality. Returns true if the two
+ // Decimal values are equal, or false if they are not equal.
+ //
+ public static bool Equals(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) == 0;
+ }
+
+ // Rounds a Decimal to an integer value. The Decimal argument is rounded
+ // towards negative infinity.
+ //
+ public static decimal Floor(decimal d)
+ {
+ int flags = d.flags;
+ if ((flags & ScaleMask) != 0)
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Floor);
+ return d;
+ }
+
+ // Converts this Decimal to a string. The resulting string consists of an
+ // optional minus sign ("-") followed to a sequence of digits ("0" - "9"),
+ // optionally followed by a decimal point (".") and another sequence of
+ // digits.
+ //
+ public override string ToString()
+ {
+ return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ public string ToString(string format)
+ {
+ return Number.FormatDecimal(this, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ return Number.FormatDecimal(this, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public string ToString(string format, IFormatProvider provider)
+ {
+ return Number.FormatDecimal(this, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null)
+ {
+ return Number.TryFormatDecimal(this, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten);
+ }
+
+ // Converts a string to a Decimal. The string must consist of an optional
+ // minus sign ("-") followed by a sequence of digits ("0" - "9"). The
+ // sequence of digits may optionally contain a single decimal point (".")
+ // character. Leading and trailing whitespace characters are allowed.
+ // Parse also allows a currency symbol, a trailing negative sign, and
+ // parentheses in the number.
+ //
+ public static decimal Parse(string s)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static decimal Parse(string s, NumberStyles style)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDecimal(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static decimal Parse(string s, IFormatProvider provider)
+ {
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static decimal Parse(string s, NumberStyles style, IFormatProvider provider)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static decimal Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Number, IFormatProvider provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static bool TryParse(string s, out decimal result)
+ {
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, out decimal result)
+ {
+ return Number.TryParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out decimal result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
+ if (s == null)
+ {
+ result = 0;
+ return false;
+ }
+
+ return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider, out decimal result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ // Returns a binary representation of a Decimal. The return value is an
+ // integer array with four elements. Elements 0, 1, and 2 contain the low,
+ // middle, and high 32 bits of the 96-bit integer part of the Decimal.
+ // Element 3 contains the scale factor and sign of the Decimal: bits 0-15
+ // (the lower word) are unused; bits 16-23 contain a value between 0 and
+ // 28, indicating the power of 10 to divide the 96-bit integer part by to
+ // produce the Decimal value; bits 24-30 are unused; and finally bit 31
+ // indicates the sign of the Decimal value, 0 meaning positive and 1
+ // meaning negative.
+ //
+ public static int[] GetBits(decimal d)
+ {
+ return new int[] { d.lo, d.mid, d.hi, d.flags };
+ }
+
+ internal static void GetBytes(decimal d, byte[] buffer)
+ {
+ Debug.Assert((buffer != null && buffer.Length >= 16), "[GetBytes]buffer != null && buffer.Length >= 16");
+ buffer[0] = (byte)d.lo;
+ buffer[1] = (byte)(d.lo >> 8);
+ buffer[2] = (byte)(d.lo >> 16);
+ buffer[3] = (byte)(d.lo >> 24);
+
+ buffer[4] = (byte)d.mid;
+ buffer[5] = (byte)(d.mid >> 8);
+ buffer[6] = (byte)(d.mid >> 16);
+ buffer[7] = (byte)(d.mid >> 24);
+
+ buffer[8] = (byte)d.hi;
+ buffer[9] = (byte)(d.hi >> 8);
+ buffer[10] = (byte)(d.hi >> 16);
+ buffer[11] = (byte)(d.hi >> 24);
+
+ buffer[12] = (byte)d.flags;
+ buffer[13] = (byte)(d.flags >> 8);
+ buffer[14] = (byte)(d.flags >> 16);
+ buffer[15] = (byte)(d.flags >> 24);
+ }
+
+ internal static decimal ToDecimal(byte[] buffer)
+ {
+ Debug.Assert((buffer != null && buffer.Length >= 16), "[ToDecimal]buffer != null && buffer.Length >= 16");
+ int lo = ((int)buffer[0]) | ((int)buffer[1] << 8) | ((int)buffer[2] << 16) | ((int)buffer[3] << 24);
+ int mid = ((int)buffer[4]) | ((int)buffer[5] << 8) | ((int)buffer[6] << 16) | ((int)buffer[7] << 24);
+ int hi = ((int)buffer[8]) | ((int)buffer[9] << 8) | ((int)buffer[10] << 16) | ((int)buffer[11] << 24);
+ int flags = ((int)buffer[12]) | ((int)buffer[13] << 8) | ((int)buffer[14] << 16) | ((int)buffer[15] << 24);
+ return new decimal(lo, mid, hi, flags);
+ }
+
+ // Returns the larger of two Decimal values.
+ //
+ internal static ref decimal Max(ref decimal d1, ref decimal d2)
+ {
+ return ref DecCalc.VarDecCmp(in d1, in d2) >= 0 ? ref d1 : ref d2;
+ }
+
+ // Returns the smaller of two Decimal values.
+ //
+ internal static ref decimal Min(ref decimal d1, ref decimal d2)
+ {
+ return ref DecCalc.VarDecCmp(in d1, in d2) < 0 ? ref d1 : ref d2;
+ }
+
+ public static decimal Remainder(decimal d1, decimal d2)
+ {
+ DecCalc.VarDecMod(ref AsMutable(ref d1), ref AsMutable(ref d2));
+ return d1;
+ }
+
+ // Multiplies two Decimal values.
+ //
+ public static decimal Multiply(decimal d1, decimal d2)
+ {
+ DecCalc.VarDecMul(ref AsMutable(ref d1), ref AsMutable(ref d2));
+ return d1;
+ }
+
+ // Returns the negated value of the given Decimal. If d is non-zero,
+ // the result is -d. If d is zero, the result is zero.
+ //
+ public static decimal Negate(decimal d)
+ {
+ return new decimal(in d, d.flags ^ SignMask);
+ }
+
+ // Rounds a Decimal value to a given number of decimal places. The value
+ // given by d is rounded to the number of decimal places given by
+ // decimals. The decimals argument must be an integer between
+ // 0 and 28 inclusive.
+ //
+ // By default a mid-point value is rounded to the nearest even number. If the mode is
+ // passed in, it can also round away from zero.
+
+ public static decimal Round(decimal d) => Round(ref d, 0, MidpointRounding.ToEven);
+ public static decimal Round(decimal d, int decimals) => Round(ref d, decimals, MidpointRounding.ToEven);
+ public static decimal Round(decimal d, MidpointRounding mode) => Round(ref d, 0, mode);
+ public static decimal Round(decimal d, int decimals, MidpointRounding mode) => Round(ref d, decimals, mode);
+
+ private static decimal Round(ref decimal d, int decimals, MidpointRounding mode)
+ {
+ if ((uint)decimals > 28)
+ throw new ArgumentOutOfRangeException(nameof(decimals), SR.ArgumentOutOfRange_DecimalRound);
+ if ((uint)mode > (uint)MidpointRounding.AwayFromZero)
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
+
+ int scale = d.Scale - decimals;
+ if (scale > 0)
+ DecCalc.InternalRound(ref AsMutable(ref d), (uint)scale, (DecCalc.RoundingMode)mode);
+ return d;
+ }
+
+ internal static int Sign(ref decimal d) => (d.lo | d.mid | d.hi) == 0 ? 0 : (d.flags >> 31) | 1;
+
+ // Subtracts two Decimal values.
+ //
+ public static decimal Subtract(decimal d1, decimal d2)
+ {
+ DecCalc.DecAddSub(ref AsMutable(ref d1), ref AsMutable(ref d2), true);
+ return d1;
+ }
+
+ // Converts a Decimal to an unsigned byte. The Decimal value is rounded
+ // towards zero to the nearest integer value, and the result of this
+ // operation is returned as a byte.
+ //
+ public static byte ToByte(decimal value)
+ {
+ uint temp;
+ try
+ {
+ temp = ToUInt32(value);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_Byte, e);
+ }
+ if (temp != (byte)temp) throw new OverflowException(SR.Overflow_Byte);
+ return (byte)temp;
+ }
+
+ // Converts a Decimal to a signed byte. The Decimal value is rounded
+ // towards zero to the nearest integer value, and the result of this
+ // operation is returned as a byte.
+ //
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(decimal value)
+ {
+ int temp;
+ try
+ {
+ temp = ToInt32(value);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_SByte, e);
+ }
+ if (temp != (sbyte)temp) throw new OverflowException(SR.Overflow_SByte);
+ return (sbyte)temp;
+ }
+
+ // Converts a Decimal to a short. The Decimal value is
+ // rounded towards zero to the nearest integer value, and the result of
+ // this operation is returned as a short.
+ //
+ public static short ToInt16(decimal value)
+ {
+ int temp;
+ try
+ {
+ temp = ToInt32(value);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_Int16, e);
+ }
+ if (temp != (short)temp) throw new OverflowException(SR.Overflow_Int16);
+ return (short)temp;
+ }
+
+ // Converts a Decimal to a double. Since a double has fewer significant
+ // digits than a Decimal, this operation may produce round-off errors.
+ //
+ public static double ToDouble(decimal d)
+ {
+ return DecCalc.VarR8FromDec(ref d);
+ }
+
+ // Converts a Decimal to an integer. The Decimal value is rounded towards
+ // zero to the nearest integer value, and the result of this operation is
+ // returned as an integer.
+ //
+ public static int ToInt32(decimal d)
+ {
+ Truncate(ref d);
+ if ((d.hi | d.mid) == 0)
+ {
+ int i = d.lo;
+ if (!d.IsNegative)
+ {
+ if (i >= 0) return i;
+ }
+ else
+ {
+ i = -i;
+ if (i <= 0) return i;
+ }
+ }
+ throw new OverflowException(SR.Overflow_Int32);
+ }
+
+ // Converts a Decimal to a long. The Decimal value is rounded towards zero
+ // to the nearest integer value, and the result of this operation is
+ // returned as a long.
+ //
+ public static long ToInt64(decimal d)
+ {
+ Truncate(ref d);
+ if (d.hi == 0)
+ {
+ long l = (long)d.Low64;
+ if (!d.IsNegative)
+ {
+ if (l >= 0) return l;
+ }
+ else
+ {
+ l = -l;
+ if (l <= 0) return l;
+ }
+ }
+ throw new OverflowException(SR.Overflow_Int64);
+ }
+
+ // Converts a Decimal to an ushort. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
+ // result of this operation is returned as an ushort.
+ //
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(decimal value)
+ {
+ uint temp;
+ try
+ {
+ temp = ToUInt32(value);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_UInt16, e);
+ }
+ if (temp != (ushort)temp) throw new OverflowException(SR.Overflow_UInt16);
+ return (ushort)temp;
+ }
+
+ // Converts a Decimal to an unsigned integer. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
+ // result of this operation is returned as an unsigned integer.
+ //
+ [CLSCompliant(false)]
+ public static uint ToUInt32(decimal d)
+ {
+ Truncate(ref d);
+ if ((d.hi | d.mid) == 0)
+ {
+ uint i = d.Low;
+ if (!d.IsNegative || i == 0)
+ return i;
+ }
+ throw new OverflowException(SR.Overflow_UInt32);
+ }
+
+ // Converts a Decimal to an unsigned long. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
+ // result of this operation is returned as a long.
+ //
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(decimal d)
+ {
+ Truncate(ref d);
+ if (d.hi == 0)
+ {
+ ulong l = d.Low64;
+ if (!d.IsNegative || l == 0)
+ return l;
+ }
+ throw new OverflowException(SR.Overflow_UInt64);
+ }
+
+ // Converts a Decimal to a float. Since a float has fewer significant
+ // digits than a Decimal, this operation may produce round-off errors.
+ //
+ public static float ToSingle(decimal d)
+ {
+ return DecCalc.VarR4FromDec(ref d);
+ }
+
+ // Truncates a Decimal to an integer value. The Decimal argument is rounded
+ // towards zero to the nearest integer value, corresponding to removing all
+ // digits after the decimal point.
+ //
+ public static decimal Truncate(decimal d)
+ {
+ Truncate(ref d);
+ return d;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void Truncate(ref decimal d)
+ {
+ int flags = d.flags;
+ if ((flags & ScaleMask) != 0)
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Truncate);
+ }
+
+ public static implicit operator decimal(byte value)
+ {
+ return new decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator decimal(sbyte value)
+ {
+ return new decimal(value);
+ }
+
+ public static implicit operator decimal(short value)
+ {
+ return new decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator decimal(ushort value)
+ {
+ return new decimal(value);
+ }
+
+ public static implicit operator decimal(char value)
+ {
+ return new decimal(value);
+ }
+
+ public static implicit operator decimal(int value)
+ {
+ return new decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator decimal(uint value)
+ {
+ return new decimal(value);
+ }
+
+ public static implicit operator decimal(long value)
+ {
+ return new decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator decimal(ulong value)
+ {
+ return new decimal(value);
+ }
+
+
+ public static explicit operator decimal(float value)
+ {
+ return new decimal(value);
+ }
+
+ public static explicit operator decimal(double value)
+ {
+ return new decimal(value);
+ }
+
+ public static explicit operator byte(decimal value)
+ {
+ return ToByte(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator sbyte(decimal value)
+ {
+ return ToSByte(value);
+ }
+
+ public static explicit operator char(decimal value)
+ {
+ ushort temp;
+ try
+ {
+ temp = ToUInt16(value);
+ }
+ catch (OverflowException e)
+ {
+ throw new OverflowException(SR.Overflow_Char, e);
+ }
+ return (char)temp;
+ }
+
+ public static explicit operator short(decimal value)
+ {
+ return ToInt16(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator ushort(decimal value)
+ {
+ return ToUInt16(value);
+ }
+
+ public static explicit operator int(decimal value)
+ {
+ return ToInt32(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator uint(decimal value)
+ {
+ return ToUInt32(value);
+ }
+
+ public static explicit operator long(decimal value)
+ {
+ return ToInt64(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator ulong(decimal value)
+ {
+ return ToUInt64(value);
+ }
+
+ public static explicit operator float(decimal value)
+ {
+ return ToSingle(value);
+ }
+
+ public static explicit operator double(decimal value)
+ {
+ return ToDouble(value);
+ }
+
+ public static decimal operator +(decimal d)
+ {
+ return d;
+ }
+
+ public static decimal operator -(decimal d)
+ {
+ return Negate(d);
+ }
+
+ public static decimal operator ++(decimal d)
+ {
+ return Add(d, One);
+ }
+
+ public static decimal operator --(decimal d)
+ {
+ return Subtract(d, One);
+ }
+
+ public static decimal operator +(decimal d1, decimal d2)
+ {
+ return Add(d1, d2);
+ }
+
+ public static decimal operator -(decimal d1, decimal d2)
+ {
+ return Subtract(d1, d2);
+ }
+
+ public static decimal operator *(decimal d1, decimal d2)
+ {
+ return Multiply(d1, d2);
+ }
+
+ public static decimal operator /(decimal d1, decimal d2)
+ {
+ return Divide(d1, d2);
+ }
+
+ public static decimal operator %(decimal d1, decimal d2)
+ {
+ return Remainder(d1, d2);
+ }
+
+ public static bool operator ==(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) == 0;
+ }
+
+ public static bool operator !=(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) != 0;
+ }
+
+ public static bool operator <(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) < 0;
+ }
+
+ public static bool operator <=(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) <= 0;
+ }
+
+ public static bool operator >(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) > 0;
+ }
+
+ public static bool operator >=(decimal d1, decimal d2)
+ {
+ return DecCalc.VarDecCmp(in d1, in d2) >= 0;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.Decimal;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(this);
+ }
+
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "Char"));
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(this);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(this);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(this);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(this);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(this);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(this);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(this);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(this);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(this);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(this);
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "DateTime"));
+ }
+
+ object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs
index 627ea4ab7..86b095e47 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs
@@ -22,11 +22,11 @@ namespace System.Diagnostics
// Fail in order to avoid anyone catching an exception and masking
// an assert failure.
DebugAssertException ex;
- if (message == String.Empty)
+ if (message == string.Empty)
{
ex = new DebugAssertException(stackTrace);
}
- else if (detailMessage == String.Empty)
+ else if (detailMessage == string.Empty)
{
ex = new DebugAssertException(message, stackTrace);
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs
new file mode 100644
index 000000000..22c9b8399
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs
@@ -0,0 +1,302 @@
+// 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.Text;
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace System.Diagnostics
+{
+ /// <summary>
+ /// There is no good reason for the methods of this class to be virtual.
+ /// </summary>
+ public partial class StackFrame
+ {
+ /// <summary>
+ /// Reflection information for the method if available, null otherwise.
+ /// </summary>
+ private MethodBase _method;
+
+ /// <summary>
+ /// Native offset of the current instruction within the current method if available,
+ /// OFFSET_UNKNOWN otherwise.
+ /// </summary>
+ private int _nativeOffset;
+
+ /// <summary>
+ /// IL offset of the current instruction within the current method if available,
+ /// OFFSET_UNKNOWN otherwise.
+ /// </summary>
+ private int _ilOffset;
+
+ /// <summary>
+ /// Source file name representing the current code location if available, null otherwise.
+ /// </summary>
+ private string _fileName;
+
+ /// <summary>
+ /// Line number representing the current code location if available, 0 otherwise.
+ /// </summary>
+ private int _lineNumber;
+
+ /// <summary>
+ /// Column number representing the current code location if available, 0 otherwise.
+ /// </summary>
+ private int _columnNumber;
+
+ /// <summary>
+ /// This flag is set to true when the frame represents a rethrow marker.
+ /// </summary>
+ private bool _isLastFrameFromForeignExceptionStackTrace;
+
+ private void InitMembers()
+ {
+ _method = null;
+ _nativeOffset = OFFSET_UNKNOWN;
+ _ilOffset = OFFSET_UNKNOWN;
+ _fileName = null;
+ _lineNumber = 0;
+ _columnNumber = 0;
+ _isLastFrameFromForeignExceptionStackTrace = false;
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to the active stack frame.
+ /// </summary>
+ public StackFrame()
+ {
+ InitMembers();
+ BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, false);
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to the active stack frame.
+ /// </summary>
+ public StackFrame(bool needFileInfo)
+ {
+ InitMembers();
+ BuildStackFrame(0 + StackTrace.METHODS_TO_SKIP, needFileInfo);
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to a calling stack frame.
+ /// </summary>
+ public StackFrame(int skipFrames)
+ {
+ InitMembers();
+ BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, false);
+ }
+
+ /// <summary>
+ /// Constructs a StackFrame corresponding to a calling stack frame.
+ /// </summary>
+ public StackFrame(int skipFrames, bool needFileInfo)
+ {
+ InitMembers();
+ BuildStackFrame(skipFrames + StackTrace.METHODS_TO_SKIP, needFileInfo);
+ }
+
+ /// <summary>
+ /// Constructs a "fake" stack frame, just containing the given file
+ /// name and line number. Use when you don't want to use the
+ /// debugger's line mapping logic.
+ /// </summary>
+ public StackFrame(string fileName, int lineNumber)
+ {
+ InitMembers();
+ BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
+ _fileName = fileName;
+ _lineNumber = lineNumber;
+ _columnNumber = 0;
+ }
+
+ /// <summary>
+ /// Constructs a "fake" stack frame, just containing the given file
+ /// name, line number and column number. Use when you don't want to
+ /// use the debugger's line mapping logic.
+ /// </summary>
+ public StackFrame(string fileName, int lineNumber, int colNumber)
+ {
+ InitMembers();
+ BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
+ _fileName = fileName;
+ _lineNumber = lineNumber;
+ _columnNumber = colNumber;
+ }
+
+ /// <summary>
+ /// Constant returned when the native or IL offset is unknown
+ /// </summary>
+ public const int OFFSET_UNKNOWN = -1;
+
+ internal virtual void SetMethodBase(MethodBase mb)
+ {
+ _method = mb;
+ }
+
+ internal virtual void SetOffset(int iOffset)
+ {
+ _nativeOffset = iOffset;
+ }
+
+ internal virtual void SetILOffset(int iOffset)
+ {
+ _ilOffset = iOffset;
+ }
+
+ internal virtual void SetFileName(string strFName)
+ {
+ _fileName = strFName;
+ }
+
+ internal virtual void SetLineNumber(int iLine)
+ {
+ _lineNumber = iLine;
+ }
+
+ internal virtual void SetColumnNumber(int iCol)
+ {
+ _columnNumber = iCol;
+ }
+
+ internal virtual void SetIsLastFrameFromForeignExceptionStackTrace(bool fIsLastFrame)
+ {
+ _isLastFrameFromForeignExceptionStackTrace = fIsLastFrame;
+ }
+
+ internal virtual bool GetIsLastFrameFromForeignExceptionStackTrace()
+ {
+ return _isLastFrameFromForeignExceptionStackTrace;
+ }
+
+ /// <summary>
+ /// Returns the method the frame is executing
+ /// </summary>
+ public virtual MethodBase GetMethod()
+ {
+ return _method;
+ }
+
+ /// <summary>
+ /// Returns the offset from the start of the native (jitted) code for the
+ /// method being executed
+ /// </summary>
+ public virtual int GetNativeOffset()
+ {
+ return _nativeOffset;
+ }
+
+
+ /// <summary>
+ /// Returns the offset from the start of the IL code for the
+ /// method being executed. This offset may be approximate depending
+ /// on whether the jitter is generating debuggable code or not.
+ /// </summary>
+ public virtual int GetILOffset()
+ {
+ return _ilOffset;
+ }
+
+ /// <summary>
+ /// Returns the file name containing the code being executed. This
+ /// information is normally extracted from the debugging symbols
+ /// for the executable.
+ /// </summary>
+ public virtual string GetFileName()
+ {
+ return _fileName;
+ }
+
+ /// <summary>
+ /// Returns the line number in the file containing the code being executed.
+ /// This information is normally extracted from the debugging symbols
+ /// for the executable.
+ /// </summary>
+ public virtual int GetFileLineNumber()
+ {
+ return _lineNumber;
+ }
+
+ /// <summary>
+ /// Returns the column number in the line containing the code being executed.
+ /// This information is normally extracted from the debugging symbols
+ /// for the executable.
+ /// </summary>
+ public virtual int GetFileColumnNumber()
+ {
+ return _columnNumber;
+ }
+
+ /// <summary>
+ /// Builds a readable representation of the stack frame
+ /// </summary>
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder(255);
+ bool includeFileInfoIfAvailable;
+
+ if (_method != null)
+ {
+ sb.Append(_method.Name);
+
+ // deal with the generic portion of the method
+ if (_method is MethodInfo methodInfo && methodInfo.IsGenericMethod)
+ {
+ Type[] typars = methodInfo.GetGenericArguments();
+
+ sb.Append('<');
+ int k = 0;
+ bool fFirstTyParam = true;
+ while (k < typars.Length)
+ {
+ if (fFirstTyParam == false)
+ sb.Append(',');
+ else
+ fFirstTyParam = false;
+
+ sb.Append(typars[k].Name);
+ k++;
+ }
+
+ sb.Append('>');
+ }
+ includeFileInfoIfAvailable = true;
+ }
+ else
+ {
+ includeFileInfoIfAvailable = AppendStackFrameWithoutMethodBase(sb);
+ }
+
+ if (includeFileInfoIfAvailable)
+ {
+ sb.Append(" at offset ");
+ if (_nativeOffset == OFFSET_UNKNOWN)
+ sb.Append("<offset unknown>");
+ else
+ sb.Append(_nativeOffset);
+
+ sb.Append(" in file:line:column ");
+
+ bool useFileName = (_fileName != null);
+
+ if (!useFileName)
+ sb.Append("<filename unknown>");
+ else
+ sb.Append(_fileName);
+ sb.Append(':');
+ sb.Append(_lineNumber);
+ sb.Append(':');
+ sb.Append(_columnNumber);
+ }
+ else
+ {
+ sb.Append("<null>");
+ }
+ sb.Append(Environment.NewLine);
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs
index 9ac32c3bd..d9f9f081c 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs
@@ -248,11 +248,6 @@ namespace System.Diagnostics.Tracing
#region private
/// <summary>
- /// The current activity ID. Use this to log normal events.
- /// </summary>
- private Guid CurrentActivityId { get { return m_current.Value.ActivityId; } }
-
- /// <summary>
/// Searched for a active (nonstopped) activity with the given name. Returns null if not found.
/// </summary>
private ActivityInfo FindActiveActivity(string name, ActivityInfo startLocation)
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs
index b036b28b4..0fed7b5c0 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs
@@ -168,6 +168,14 @@ namespace System.Diagnostics.Tracing
}
}
+ internal int TraceLoggingId
+ {
+ get
+ {
+ return m_traceloggingId;
+ }
+ }
+
public override bool Equals(object obj)
{
if (!(obj is EventDescriptor))
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs
index fafdd7c6d..36b363fa3 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs
@@ -30,6 +30,13 @@ namespace Microsoft.Diagnostics.Tracing
namespace System.Diagnostics.Tracing
#endif
{
+ internal enum EventProviderType
+ {
+ None = 0,
+ ETW,
+ EventPipe
+ };
+
// New in CLR4.0
internal enum ControllerCommand
{
@@ -120,15 +127,28 @@ namespace System.Diagnostics.Tracing
// it registers a callback from native code you MUST dispose it BEFORE shutdown, otherwise
// you may get native callbacks during shutdown when we have destroyed the delegate.
// EventSource has special logic to do this, no one else should be calling EventProvider.
- internal EventProvider()
+ internal EventProvider(EventProviderType providerType)
{
+ switch (providerType)
+ {
+ case EventProviderType.ETW:
#if PLATFORM_WINDOWS
- m_eventProvider = new EtwEventProvider();
-#elif FEATURE_PERFTRACING
- m_eventProvider = new EventPipeEventProvider();
+ m_eventProvider = new EtwEventProvider();
+#else
+ m_eventProvider = new NoOpEventProvider();
+#endif
+ break;
+ case EventProviderType.EventPipe:
+#if FEATURE_PERFTRACING
+ m_eventProvider = new EventPipeEventProvider();
#else
- m_eventProvider = new NoOpEventProvider();
+ m_eventProvider = new NoOpEventProvider();
#endif
+ break;
+ default:
+ m_eventProvider = new NoOpEventProvider();
+ break;
+ };
}
/// <summary>
@@ -331,7 +351,7 @@ namespace System.Diagnostics.Tracing
protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = unchecked((long)value); } }
protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = unchecked((long)value); } }
- static private int FindNull(byte[] buffer, int idx)
+ private static int FindNull(byte[] buffer, int idx)
{
while (idx < buffer.Length && buffer[idx] != 0)
idx++;
@@ -475,7 +495,7 @@ namespace System.Diagnostics.Tracing
var structBase = (byte*)providerInstance;
providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
}
-#else
+#else
#if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds...
// This code is only used in the Nuget Package Version of EventSource. because
// the code above is using APIs baned from UWP apps.
@@ -761,10 +781,10 @@ namespace System.Diagnostics.Tracing
*uintptr = (uint)data;
dataDescriptor->Ptr = (ulong)uintptr;
}
- else if (data is UInt64)
+ else if (data is ulong)
{
dataDescriptor->Size = (uint)sizeof(ulong);
- UInt64* ulongptr = (ulong*)dataBuffer;
+ ulong* ulongptr = (ulong*)dataBuffer;
*ulongptr = (ulong)data;
dataDescriptor->Ptr = (ulong)ulongptr;
}
@@ -863,25 +883,18 @@ namespace System.Diagnostics.Tracing
{
if (data is System.Enum)
{
- Type underlyingType = Enum.GetUnderlyingType(data.GetType());
- if (underlyingType == typeof(int))
- {
-#if !ES_BUILD_PCL
- data = ((IConvertible)data).ToInt32(null);
-#else
- data = (int)data;
-#endif
- goto Again;
- }
- else if (underlyingType == typeof(long))
+ try
{
-#if !ES_BUILD_PCL
- data = ((IConvertible)data).ToInt64(null);
-#else
- data = (long)data;
-#endif
+ Type underlyingType = Enum.GetUnderlyingType(data.GetType());
+ if (underlyingType == typeof(ulong))
+ data = (ulong)data;
+ else if (underlyingType == typeof(long))
+ data = (long)data;
+ else
+ data = (int)Convert.ToInt64(data); // This handles all int/uint or below (we treat them like 32 bit ints)
goto Again;
}
+ catch { } // On wierd cases (e.g. enums of type double), give up and for compat simply tostring.
}
// To our eyes, everything else is a just a string
@@ -959,7 +972,7 @@ namespace System.Diagnostics.Tracing
List<object> dataRefObj = new List<object>(s_etwAPIMaxRefObjCount);
EventData* userData = stackalloc EventData[2 * argCount];
for (int i = 0; i < 2 * argCount; i++)
- userData[i] = default(EventData);
+ userData[i] = default;
EventData* userDataPtr = (EventData*)userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * 2 * argCount]; // Assume 16 chars for non-string argument
byte* currentBuffer = dataBuffer;
@@ -1133,7 +1146,7 @@ namespace System.Diagnostics.Tracing
// <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
- internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
+ internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
{
if (childActivityID != null)
{
@@ -1157,6 +1170,7 @@ namespace System.Diagnostics.Tracing
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
internal unsafe bool WriteEventRaw(
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityID,
Guid* relatedActivityID,
int dataCount,
@@ -1167,7 +1181,7 @@ namespace System.Diagnostics.Tracing
status = m_eventProvider.EventWriteTransferWrapper(
m_regHandle,
ref eventDescriptor,
- IntPtr.Zero,
+ eventHandle,
activityID,
relatedActivityID,
dataCount,
@@ -1269,14 +1283,13 @@ namespace System.Diagnostics.Tracing
}
// Define an EventPipeEvent handle.
- unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
{
throw new System.NotSupportedException();
}
}
-#elif !FEATURE_PERFTRACING
-
+#endif
internal sealed class NoOpEventProvider : IEventProvider
{
unsafe uint IEventProvider.EventRegister(
@@ -1311,12 +1324,10 @@ namespace System.Diagnostics.Tracing
}
// Define an EventPipeEvent handle.
- unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
{
- throw new System.NotSupportedException();
+ return IntPtr.Zero;
}
}
-
-#endif
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs
index 40d39ced7..b309eb5aa 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs
@@ -18,12 +18,12 @@
//
// PRINCIPLE: EventSource - ETW decoupling
//
-// Conceptually and EventSouce is something takes event logging data from the source methods
-// To the EventListener that can subscribe them. Note that CONCEPTUALLY EVENTSOURCES DON'T
-// KNOW ABOUT ETW!. The MODEL of the system is that there is a special EventListener Which
+// Conceptually an EventSouce is something that takes event logging data from the source methods
+// to the EventListener that can subscribe to them. Note that CONCEPTUALLY EVENTSOURCES DON'T
+// KNOW ABOUT ETW!. The MODEL of the system is that there is a special EventListener which
// we will call the EtwEventListener, that forwards commands from ETW to EventSources and
-// listeners to the EventSources and forwards on those events to ETW. THus the model should
-// be that you DON'T NEED ETW.
+// listens to EventSources and forwards on those events to ETW. Thus the model should
+// be that you DON'T NEED ETW.
//
// Now in actual practice, EventSouce have rather intimate knowledge of ETW and send events
// to it directly, but this can be VIEWED AS AN OPTIMIZATION.
@@ -33,20 +33,20 @@
// There are two ways for event Data to enter the system
// 1) WriteEvent* and friends. This is called the 'contract' based approach because
// you write a method per event which forms a contract that is know at compile time.
-// In this scheme each event is given an EVENTID (small integer). which is its identity
+// In this scheme each event is given an EVENTID (small integer), which is its identity
// 2) Write<T> methods. This is called the 'dynamic' approach because new events
// can be created on the fly. Event identity is determined by the event NAME, and these
// are not quite as efficient at runtime since you have at least a hash table lookup
// on every event write.
//
-// EventSource-EventListener transfer fully support both ways of writing events (either contract
-// based (WriteEvent*) or dynamic (Write<T>). Both way fully support the same set of data
-// types. It is suggested, however, that you use the contract based approach when the event scheme
+// EventSource-EventListener transfer fully supports both ways of writing events (either contract
+// based (WriteEvent*) or dynamic (Write<T>)). Both ways fully support the same set of data
+// types. It is recommended, however, that you use the contract based approach when the event scheme
// is known at compile time (that is whenever possible). It is more efficient, but more importantly
// it makes the contract very explicit, and centralizes all policy about logging. These are good
-// things. The Write<T> API is really meant for more ad-hoc
+// things. The Write<T> API is really meant for more ad-hoc cases.
//
-// Allowed Data.
+// Allowed Data:
//
// Note that EventSource-EventListeners have a conceptual serialization-deserialization that happens
// during the transfer. In particular object identity is not preserved, some objects are morphed,
@@ -57,7 +57,7 @@
// * IEnumerable<T> of valid types T (this include arrays) (* New for V4.6)
// * Explicitly Opted in class or struct with public property Getters over Valid types. (* New for V4.6)
//
-// This set of types is roughly a generalization of JSON support (Basically primitives, bags, and arrays).
+// This set of types is roughly a generalization of JSON support (basically primitives, bags, and arrays).
//
// Explicitly allowed structs include (* New for V4.6)
// * Marked with the EventData attribute
@@ -67,27 +67,27 @@
// When classes are returned in an EventListener, what is returned is something that implements
// IDictionary<string, T>. Thus when objects are passed to an EventSource they are transformed
// into a key-value bag (the IDictionary<string, T>) for consumption in the listener. These
-// are obvious NOT the original objects.
+// are obviously NOT the original objects.
//
-// ETWserialization formats:
+// ETW serialization formats:
//
-// As mentioned conceptually EventSource's send data to EventListeners and there is a conceptual
+// As mentioned, conceptually EventSources send data to EventListeners and there is a conceptual
// copy/morph of that data as described above. In addition the .NET framework supports a conceptual
-// ETWListener that will send the data to then ETW stream. If you use this feature, the data needs
+// ETWListener that will send the data to the ETW stream. If you use this feature, the data needs
// to be serialized in a way that ETW supports. ETW supports the following serialization formats
//
// 1) Manifest Based serialization.
// 2) SelfDescribing serialization (TraceLogging style in the TraceLogging directory)
//
-// A key factor is that the Write<T> method, which support on the fly definition of events, can't
+// A key factor is that the Write<T> method, which supports on the fly definition of events, can't
// support the manifest based serialization because the manifest needs the schema of all events
-// to be known before any events are emitted. This implies the following
+// to be known before any events are emitted. This implies the following:
//
// If you use Write<T> and the output goes to ETW it will use the SelfDescribing format.
// If you use the EventSource(string) constructor for an eventSource (in which you don't
// create a subclass), the default is also to use Self-Describing serialization. In addition
// you can use the EventSoruce(EventSourceSettings) constructor to also explicitly specify
-// Self-Describing serialization format. These effect the WriteEvent* APIs going to ETW.
+// Self-Describing serialization format. These affect the WriteEvent* APIs going to ETW.
//
// Note that none of this ETW serialization logic affects EventListeners. Only the ETW listener.
//
@@ -111,13 +111,13 @@
//
// On output there are the following routines
// Writing to all listeners that are NOT ETW, we have the following routines
-// * WriteToAllListeners(ID, Guid*, COUNT, EventData*)
-// * WriteToAllListeners(ID, Guid*, object[])
-// * WriteToAllListeners(NAME, Guid*, EventPayload)
+// * WriteToAllListeners(ID, Guid*, Guid*, COUNT, EventData*)
+// * WriteToAllListeners(ID, Guid*, Guid*, object[])
+// * WriteToAllListeners(NAME, Guid*, Guid*, EventPayload)
//
// EventPayload is the internal type that implements the IDictionary<string, object> interface
// The EventListeners will pass back for serialized classes for nested object, but
-// WriteToAllListeners(NAME, Guid*, EventPayload) unpacks this uses the fields as if they
+// WriteToAllListeners(NAME, Guid*, Guid*, EventPayload) unpacks this and uses the fields as if they
// were parameters to a method.
//
// The first two are used for the WriteEvent* case, and the later is used for the Write<T> case.
@@ -129,7 +129,7 @@
// WriteMultiMerge(NAME, Options, Types, EventData*)
// WriteMultiMerge(NAME, Options, Types, object[])
// WriteImpl<T> has logic that knows how to serialize (like WriteMultiMerge) but also knows
-// will write it to
+// where it will write it to
//
// All ETW writes eventually call
// EventWriteTransfer (native PINVOKE wrapper)
@@ -146,7 +146,7 @@
// since it is the TraceLoggingTypeInfo structure that knows how to do this. Effectively for a type you
// can call one of these
// WriteMetadata - transforms the type T into serialization meta data blob for that type
-// WriteObjectData - transforms an object of T into serialization meta data blob for that type
+// WriteObjectData - transforms an object of T into serialization data blob for that instance
// GetData - transforms an object of T into its deserialized form suitable for passing to EventListener.
// The first two are used to serialize something for ETW. The second one is used to transform the object
// for use by the EventListener. We also have a 'DecodeObject' method that will take a EventData* and
@@ -181,6 +181,7 @@ using System.Security.Permissions;
using System.Text;
using System.Threading;
using Microsoft.Win32;
+using Internal.Runtime.Augments;
#if ES_BUILD_STANDALONE
using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
@@ -196,10 +197,6 @@ using Contract = System.Diagnostics.Contracts.Contract;
using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
#endif
-#if CORECLR || ES_BUILD_PN
-using Internal.Runtime.Augments;
-#endif
-
#if ES_BUILD_STANDALONE
namespace Microsoft.Diagnostics.Tracing
#else
@@ -434,7 +431,7 @@ namespace System.Diagnostics.Tracing
throw new ArgumentException(SR.EventSource_InvalidCommand, nameof(command));
}
- eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
+ eventSource.SendCommand(null, EventProviderType.ETW, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
}
#if !ES_BUILD_STANDALONE
@@ -537,7 +534,7 @@ namespace System.Diagnostics.Tracing
}
}
- #region protected
+#region protected
/// <summary>
/// This is the constructor that most users will use to create their eventSource. It takes
/// no parameters. The ETW provider name and GUID of the EventSource are determined by the EventSource
@@ -606,8 +603,15 @@ namespace System.Diagnostics.Tracing
// typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
private unsafe void DefineEventPipeEvents()
{
+ // If the EventSource is set to emit all events as TraceLogging events, skip this initialization.
+ // Events will be defined when they are emitted for the first time.
+ if(SelfDescribingEvents)
+ {
+ return;
+ }
+
Debug.Assert(m_eventData != null);
- Debug.Assert(m_provider != null);
+ Debug.Assert(m_eventPipeProvider != null);
int cnt = m_eventData.Length;
for (int i = 0; i < cnt; i++)
{
@@ -615,102 +619,30 @@ namespace System.Diagnostics.Tracing
if (eventID == 0)
continue;
+ byte[] metadata = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(m_eventData[i]);
+ uint metadataLength = (metadata != null) ? (uint)metadata.Length : 0;
+
string eventName = m_eventData[i].Name;
- Int64 keywords = m_eventData[i].Descriptor.Keywords;
+ long keywords = m_eventData[i].Descriptor.Keywords;
uint eventVersion = m_eventData[i].Descriptor.Version;
uint level = m_eventData[i].Descriptor.Level;
- // evnetID : 4 bytes
- // eventName : (eventName.Length + 1) * 2 bytes
- // keywords : 8 bytes
- // eventVersion : 4 bytes
- // level : 4 bytes
- // parameterCount : 4 bytes
- uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
-
- // Increase the metadataLength for the types of all parameters.
- metadataLength += (uint)m_eventData[i].Parameters.Length * 4;
-
- // Increase the metadataLength for the names of all parameters.
- foreach (var parameter in m_eventData[i].Parameters)
- {
- string parameterName = parameter.Name;
- metadataLength = metadataLength + ((uint)parameterName.Length + 1) * 2;
- }
-
- byte[] metadata = new byte[metadataLength];
-
- // Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
fixed (byte *pMetadata = metadata)
{
- uint offset = 0;
- WriteToBuffer(pMetadata, metadataLength, ref offset, eventID);
- fixed(char *pEventName = eventName)
- {
- WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
- }
- WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
- WriteToBuffer(pMetadata, metadataLength, ref offset, eventVersion);
- WriteToBuffer(pMetadata, metadataLength, ref offset, level);
- WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)m_eventData[i].Parameters.Length);
- foreach (var parameter in m_eventData[i].Parameters)
- {
- // Write parameter type.
- WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)GetTypeCodeExtended(parameter.ParameterType));
-
- // Write parameter name.
- string parameterName = parameter.Name;
- fixed (char *pParameterName = parameterName)
- {
- WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pParameterName, ((uint)parameterName.Length + 1) * 2);
- }
- }
- Debug.Assert(metadataLength == offset);
- IntPtr eventHandle = m_provider.m_eventProvider.DefineEventHandle(eventID, eventName, keywords, eventVersion, level, pMetadata, metadataLength);
- m_eventData[i].EventHandle = eventHandle;
+ IntPtr eventHandle = m_eventPipeProvider.m_eventProvider.DefineEventHandle(
+ eventID,
+ eventName,
+ keywords,
+ eventVersion,
+ level,
+ pMetadata,
+ metadataLength);
+
+ Debug.Assert(eventHandle != IntPtr.Zero);
+ m_eventData[i].EventHandle = eventHandle;
}
}
}
-
- // Copy src to buffer and modify the offset.
- // Note: We know the buffer size ahead of time to make sure no buffer overflow.
- private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
- {
- Debug.Assert(bufferLength >= (offset + srcLength));
- for (int i = 0; i < srcLength; i++)
- {
- *(byte *)(buffer + offset + i) = *(byte *)(src + i);
- }
- offset += srcLength;
- }
-
- // Copy uint value to buffer.
- private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, uint value)
- {
- Debug.Assert(bufferLength >= (offset + 4));
- *(uint *)(buffer + offset) = value;
- offset += 4;
- }
-
- // Copy long value to buffer.
- private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, long value)
- {
- Debug.Assert(bufferLength >= (offset + 8));
- *(long *)(buffer + offset) = value;
- offset += 8;
- }
-
- private static TypeCode GetTypeCodeExtended(Type parameterType)
- {
- // Guid is not part of TypeCode, we decided to use 17 to represent it, as it's the "free slot"
- // see https://github.com/dotnet/coreclr/issues/16105#issuecomment-361749750 for more
- const TypeCode GuidTypeCode = (TypeCode)17;
-
- if (parameterType == typeof(Guid)) // Guid is not a part of TypeCode enum
- return GuidTypeCode;
-
- return Type.GetTypeCode(parameterType);
- }
#endif
internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
@@ -966,7 +898,7 @@ namespace System.Diagnostics.Tracing
EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
descrs[0].DataPointer = (IntPtr)string1Bytes;
descrs[0].Size = ((arg1.Length + 1) * 2);
- descrs[1].Reserved = 0;
+ descrs[0].Reserved = 0;
descrs[1].DataPointer = (IntPtr)(&arg2);
descrs[1].Size = 8;
descrs[1].Reserved = 0;
@@ -1112,7 +1044,7 @@ namespace System.Diagnostics.Tracing
/// </summary>
internal int Reserved { get { return m_Reserved; } set { m_Reserved = value; } }
- #region private
+#region private
/// <summary>
/// Initializes the members of this EventData object to point at a previously-pinned
/// tracelogging-compatible metadata blob.
@@ -1134,7 +1066,7 @@ namespace System.Diagnostics.Tracing
#pragma warning disable 0649
internal int m_Reserved; // Used to pad the size to match the Win32 API
#pragma warning restore 0649
- #endregion
+#endregion
}
/// <summary>
@@ -1230,12 +1162,20 @@ namespace System.Diagnostics.Tracing
}
#if FEATURE_MANAGED_ETW
- if (m_eventData[eventId].EnabledForETW)
+ if (m_eventData[eventId].EnabledForETW
+#if FEATURE_PERFTRACING
+ || m_eventData[eventId].EnabledForEventPipe
+#endif // FEATURE_PERFTRACING
+ )
{
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_etwProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
+#if FEATURE_PERFTRACING
+ if (!m_eventPipeProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+#endif // FEATURE_PERFTRACING
}
else
{
@@ -1261,7 +1201,7 @@ namespace System.Diagnostics.Tracing
#endif // FEATURE_MANAGED_ETW
if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
- WriteToAllListeners(eventId, relatedActivityId, eventDataCount, data);
+ WriteToAllListeners(eventId, pActivityId, relatedActivityId, eventDataCount, data);
}
catch (Exception ex)
{
@@ -1300,9 +1240,9 @@ namespace System.Diagnostics.Tracing
WriteEventVarargs(eventId, &relatedActivityId, args);
}
- #endregion
+#endregion
- #region IDisposable Members
+#region IDisposable Members
/// <summary>
/// Disposes of an EventSource.
/// </summary>
@@ -1326,7 +1266,6 @@ namespace System.Diagnostics.Tracing
if (disposing)
{
#if FEATURE_MANAGED_ETW
-#if !FEATURE_PERFTRACING
// Send the manifest one more time to ensure circular buffers have a chance to get to this information
// even in scenarios with a high volume of ETW events.
if (m_eventSourceEnabled)
@@ -1339,11 +1278,17 @@ namespace System.Diagnostics.Tracing
{ } // If it fails, simply give up.
m_eventSourceEnabled = false;
}
+ if (m_etwProvider != null)
+ {
+ m_etwProvider.Dispose();
+ m_etwProvider = null;
+ }
#endif
- if (m_provider != null)
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider != null)
{
- m_provider.Dispose();
- m_provider = null;
+ m_eventPipeProvider.Dispose();
+ m_eventPipeProvider = null;
}
#endif
}
@@ -1357,29 +1302,41 @@ namespace System.Diagnostics.Tracing
{
this.Dispose(false);
}
- #endregion
+#endregion
- #region private
+#region private
private unsafe void WriteEventRaw(
string eventName,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityID,
Guid* relatedActivityID,
int dataCount,
IntPtr data)
{
#if FEATURE_MANAGED_ETW
- if (m_provider == null)
+ if (m_etwProvider == null)
{
ThrowEventSourceException(eventName);
}
else
{
- if (!m_provider.WriteEventRaw(ref eventDescriptor, activityID, relatedActivityID, dataCount, data))
+ if (!m_etwProvider.WriteEventRaw(ref eventDescriptor, eventHandle, activityID, relatedActivityID, dataCount, data))
ThrowEventSourceException(eventName);
}
#endif // FEATURE_MANAGED_ETW
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider == null)
+ {
+ ThrowEventSourceException(eventName);
+ }
+ else
+ {
+ if (!m_eventPipeProvider.WriteEventRaw(ref eventDescriptor, eventHandle, activityID, relatedActivityID, dataCount, data))
+ ThrowEventSourceException(eventName);
+ }
+#endif // FEATURE_PERFTRACING
}
// FrameworkEventSource is on the startup path for the framework, so we have this internal overload that it can use
@@ -1428,14 +1385,20 @@ namespace System.Diagnostics.Tracing
//Enable Implicit Activity tracker
m_activityTracker = ActivityTracker.Instance;
-#if FEATURE_MANAGED_ETW
+#if FEATURE_MANAGED_ETW || FEATURE_PERFTRACING
// Create and register our provider traits. We do this early because it is needed to log errors
// In the self-describing event case.
this.InitializeProviderMetadata();
-
+#endif
+#if FEATURE_MANAGED_ETW
// Register the provider with ETW
- var provider = new OverideEventProvider(this);
- provider.Register(this);
+ var etwProvider = new OverideEventProvider(this, EventProviderType.ETW);
+ etwProvider.Register(this);
+#endif
+#if FEATURE_PERFTRACING
+ // Register the provider with EventPipe
+ var eventPipeProvider = new OverideEventProvider(this, EventProviderType.EventPipe);
+ eventPipeProvider.Register(this);
#endif
// Add the eventSource to the global (weak) list.
// This also sets m_id, which is the index in the list.
@@ -1444,7 +1407,7 @@ namespace System.Diagnostics.Tracing
#if FEATURE_MANAGED_ETW
// OK if we get this far without an exception, then we can at least write out error messages.
// Set m_provider, which allows this.
- m_provider = provider;
+ m_etwProvider = etwProvider;
#if PLATFORM_WINDOWS
#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN)
@@ -1458,7 +1421,7 @@ namespace System.Diagnostics.Tracing
System.Runtime.InteropServices.GCHandle.Alloc(this.providerMetadata, System.Runtime.InteropServices.GCHandleType.Pinned);
IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
- setInformationResult = m_provider.SetInformation(
+ setInformationResult = m_etwProvider.SetInformation(
UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
providerMetadata,
(uint)this.providerMetadata.Length);
@@ -1467,6 +1430,10 @@ namespace System.Diagnostics.Tracing
}
#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW
+
+#if FEATURE_PERFTRACING
+ m_eventPipeProvider = eventPipeProvider;
+#endif
Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
// We are logically completely initialized at this point.
m_completelyInited = true;
@@ -1683,6 +1650,14 @@ namespace System.Diagnostics.Tracing
private static Guid GenerateGuidFromName(string name)
{
+ if (namespaceBytes == null)
+ {
+ namespaceBytes = new byte[] {
+ 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
+ 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
+ };
+ }
+
byte[] bytes = Encoding.BigEndianUnicode.GetBytes(name);
var hash = new Sha1ForNonSecretPurposes();
hash.Start();
@@ -1810,10 +1785,16 @@ namespace System.Diagnostics.Tracing
if (dataType.IsEnum())
{
dataType = Enum.GetUnderlyingType(dataType);
+#if ES_BUILD_PN
+ int dataTypeSize = (int)dataType.TypeHandle.ToEETypePtr().ValueTypeSize;
+#else
+ int dataTypeSize = System.Runtime.InteropServices.Marshal.SizeOf(dataType);
+#endif
+ if (dataTypeSize < sizeof(int))
+ dataType = typeof(int);
goto Again;
}
-
// Everything else is marshaled as a string.
// ETW strings are NULL-terminated, so marshal everything up to the first
// null in the string.
@@ -1824,7 +1805,6 @@ namespace System.Diagnostics.Tracing
}
return new string((char *)dataPointer);
-
}
finally
{
@@ -1899,12 +1879,20 @@ namespace System.Diagnostics.Tracing
}
#if FEATURE_MANAGED_ETW
- if (m_eventData[eventId].EnabledForETW)
+ if (m_eventData[eventId].EnabledForETW
+#if FEATURE_PERFTRACING
+ || m_eventData[eventId].EnabledForEventPipe
+#endif // FEATURE_PERFTRACING
+ )
{
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
+ if (!m_etwProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+#if FEATURE_PERFTRACING
+ if (!m_eventPipeProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
+#endif // FEATURE_PERFTRACING
}
else
{
@@ -1929,19 +1917,31 @@ namespace System.Diagnostics.Tracing
}
}
#endif // FEATURE_MANAGED_ETW
- if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
+ if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
{
#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN)
// Maintain old behavior - object identity is preserved
if (AppContextSwitches.PreserveEventListnerObjectIdentity)
{
- WriteToAllListeners(eventId, childActivityID, args);
+ WriteToAllListeners(
+ eventId: eventId,
+ osThreadId: null,
+ timeStamp: null,
+ activityID: pActivityId,
+ childActivityID: childActivityID,
+ args: args);
}
else
#endif // !ES_BUILD_STANDALONE
{
object[] serializedArgs = SerializeEventArgs(eventId, args);
- WriteToAllListeners(eventId, childActivityID, serializedArgs);
+ WriteToAllListeners(
+ eventId: eventId,
+ osThreadId: null,
+ timeStamp: null,
+ activityID: pActivityId,
+ childActivityID: childActivityID,
+ args: serializedArgs);
}
}
}
@@ -1955,7 +1955,7 @@ namespace System.Diagnostics.Tracing
}
}
- unsafe private object[] SerializeEventArgs(int eventId, object[] args)
+ private unsafe object[] SerializeEventArgs(int eventId, object[] args)
{
TraceLoggingEventTypes eventTypes = m_eventData[eventId].TraceLoggingEventTypes;
if (eventTypes == null)
@@ -2012,7 +2012,7 @@ namespace System.Diagnostics.Tracing
#endif //!ES_BUILD_PCL
}
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
+ private unsafe void WriteToAllListeners(int eventId, Guid* activityID, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
{
// We represent a byte[] as a integer denoting the length and then a blob of bytes in the data pointer. This causes a spurious
// warning because eventDataCount is off by one for the byte[] case since a byte[] has 2 items associated it. So we want to check
@@ -2043,14 +2043,26 @@ namespace System.Diagnostics.Tracing
EventSource.EventData* dataPtr = data;
for (int i = 0; i < paramCount; i++)
args[i] = DecodeObject(eventId, i, ref dataPtr);
- WriteToAllListeners(eventId, childActivityID, args);
+ WriteToAllListeners(
+ eventId: eventId,
+ osThreadId: null,
+ timeStamp: null,
+ activityID: activityID,
+ childActivityID: childActivityID,
+ args: args);
}
// helper for writing to all EventListeners attached the current eventSource.
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, params object[] args)
+ internal unsafe void WriteToAllListeners(int eventId, uint* osThreadId, DateTime* timeStamp, Guid* activityID, Guid* childActivityID, params object[] args)
{
EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
eventCallbackArgs.EventId = eventId;
+ if (osThreadId != null)
+ eventCallbackArgs.OSThreadId = (int)*osThreadId;
+ if (timeStamp != null)
+ eventCallbackArgs.TimeStamp = *timeStamp;
+ if (activityID != null)
+ eventCallbackArgs.ActivityId = *activityID;
if (childActivityID != null)
eventCallbackArgs.RelatedActivityId = *childActivityID;
eventCallbackArgs.EventName = m_eventData[eventId].Name;
@@ -2092,8 +2104,8 @@ namespace System.Diagnostics.Tracing
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
private unsafe void WriteEventString(EventLevel level, long keywords, string msgString)
{
-#if FEATURE_MANAGED_ETW && !FEATURE_PERFTRACING
- if (m_provider != null)
+#if FEATURE_MANAGED_ETW
+ if (m_etwProvider != null)
{
string eventName = "EventSourceMessage";
if (SelfDescribingEvents)
@@ -2128,7 +2140,7 @@ namespace System.Diagnostics.Tracing
data.Ptr = (ulong)msgStringPtr;
data.Size = (uint)(2 * (msgString.Length + 1));
data.Reserved = 0;
- m_provider.WriteEvent(ref descr, IntPtr.Zero, null, null, 1, (IntPtr)((void*)&data));
+ m_etwProvider.WriteEvent(ref descr, IntPtr.Zero, null, null, 1, (IntPtr)((void*)&data));
}
}
}
@@ -2273,7 +2285,10 @@ namespace System.Diagnostics.Tracing
break;
default:
if (innerEx != null)
+ {
+ innerEx = innerEx.GetBaseException();
ReportOutOfBandMessage(errorPrefix + ": " + innerEx.GetType() + ":" + innerEx.Message, true);
+ }
else
ReportOutOfBandMessage(errorPrefix, true);
if (ThrowOnEventWriteErrors) throw new EventSourceException(innerEx);
@@ -2319,19 +2334,22 @@ namespace System.Diagnostics.Tracing
/// </summary>
private class OverideEventProvider : EventProvider
{
- public OverideEventProvider(EventSource eventSource)
+ public OverideEventProvider(EventSource eventSource, EventProviderType providerType)
+ : base(providerType)
{
this.m_eventSource = eventSource;
+ this.m_eventProviderType = providerType;
}
protected override void OnControllerCommand(ControllerCommand command, IDictionary<string, string> arguments,
int perEventSourceSessionId, int etwSessionId)
{
// We use null to represent the ETW EventListener.
EventListener listener = null;
- m_eventSource.SendCommand(listener, perEventSourceSessionId, etwSessionId,
+ m_eventSource.SendCommand(listener, m_eventProviderType, perEventSourceSessionId, etwSessionId,
(EventCommand)command, IsEnabled(), Level, MatchAnyKeyword, arguments);
}
private EventSource m_eventSource;
+ private EventProviderType m_eventProviderType;
}
#endif
@@ -2360,7 +2378,10 @@ namespace System.Diagnostics.Tracing
public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
public bool EnabledForAnyListener; // true if any dispatcher has this event turned on
- public bool EnabledForETW; // is this event on for the OS ETW data dispatcher?
+ public bool EnabledForETW; // is this event on for ETW?
+#if FEATURE_PERFTRACING
+ public bool EnabledForEventPipe; // is this event on for EventPipe?
+#endif
public bool HasRelatedActivityID; // Set if the event method's first parameter is a Guid named 'relatedActivityId'
#pragma warning disable 0649
@@ -2404,12 +2425,12 @@ namespace System.Diagnostics.Tracing
// * The 'enabled' 'level', matchAnyKeyword' arguments are ignored (must be true, 0, 0).
//
// dispatcher == null has special meaning. It is the 'ETW' dispatcher.
- internal void SendCommand(EventListener listener, int perEventSourceSessionId, int etwSessionId,
+ internal void SendCommand(EventListener listener, EventProviderType eventProviderType, int perEventSourceSessionId, int etwSessionId,
EventCommand command, bool enable,
EventLevel level, EventKeywords matchAnyKeyword,
IDictionary<string, string> commandArguments)
{
- var commandArgs = new EventCommandEventArgs(command, commandArguments, this, listener, perEventSourceSessionId, etwSessionId, enable, level, matchAnyKeyword);
+ var commandArgs = new EventCommandEventArgs(command, commandArguments, this, listener, eventProviderType, perEventSourceSessionId, etwSessionId, enable, level, matchAnyKeyword);
lock (EventListener.EventListenersLock)
{
if (m_completelyInited)
@@ -2449,9 +2470,13 @@ namespace System.Diagnostics.Tracing
Debug.Assert(m_completelyInited);
#if FEATURE_MANAGED_ETW
- if (m_provider == null) // If we failed to construct
+ if (m_etwProvider == null) // If we failed to construct
return;
#endif // FEATURE_MANAGED_ETW
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider == null)
+ return;
+#endif
m_outOfBandMessageCount = 0;
bool shouldReport = (commandArgs.perEventSourceSessionId > 0) && (commandArgs.perEventSourceSessionId <= SessionMask.MAX);
@@ -2474,7 +2499,7 @@ namespace System.Diagnostics.Tracing
{
// Set it up using the 'standard' filtering bitfields (use the "global" enable, not session specific one)
for (int i = 0; i < m_eventData.Length; i++)
- EnableEventForDispatcher(commandArgs.dispatcher, i, IsEnabledByDefault(i, commandArgs.enable, commandArgs.level, commandArgs.matchAnyKeyword));
+ EnableEventForDispatcher(commandArgs.dispatcher, commandArgs.eventProviderType, i, IsEnabledByDefault(i, commandArgs.enable, commandArgs.level, commandArgs.matchAnyKeyword));
if (commandArgs.enable)
{
@@ -2524,13 +2549,11 @@ namespace System.Diagnostics.Tracing
{
// eventSourceDispatcher == null means this is the ETW manifest
-#if !FEATURE_PERFTRACING
// Note that we unconditionally send the manifest whenever we are enabled, even if
// we were already enabled. This is because there may be multiple sessions active
// and we can't know that all the sessions have seen the manifest.
if (!SelfDescribingEvents)
SendManifest(m_rawManifest);
-#endif
}
// Turn on the enable bit before making the OnEventCommand callback This allows you to do useful
@@ -2612,16 +2635,20 @@ namespace System.Diagnostics.Tracing
/// of 'eventId. If value is 'false' disable the event for that dispatcher. If 'eventId' is out of
/// range return false, otherwise true.
/// </summary>
- internal bool EnableEventForDispatcher(EventDispatcher dispatcher, int eventId, bool value)
+ internal bool EnableEventForDispatcher(EventDispatcher dispatcher, EventProviderType eventProviderType, int eventId, bool value)
{
if (dispatcher == null)
{
if (eventId >= m_eventData.Length)
return false;
#if FEATURE_MANAGED_ETW
- if (m_provider != null)
+ if (m_etwProvider != null && eventProviderType == EventProviderType.ETW)
m_eventData[eventId].EnabledForETW = value;
#endif
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider != null && eventProviderType == EventProviderType.EventPipe)
+ m_eventData[eventId].EnabledForEventPipe = value;
+#endif
}
else
{
@@ -2640,7 +2667,11 @@ namespace System.Diagnostics.Tracing
private bool AnyEventEnabled()
{
for (int i = 0; i < m_eventData.Length; i++)
- if (m_eventData[i].EnabledForETW || m_eventData[i].EnabledForAnyListener)
+ if (m_eventData[i].EnabledForETW || m_eventData[i].EnabledForAnyListener
+#if FEATURE_PERFTRACING
+ || m_eventData[i].EnabledForEventPipe
+#endif // FEATURE_PERFTRACING
+ )
return true;
return false;
}
@@ -2730,7 +2761,7 @@ namespace System.Diagnostics.Tracing
Debug.Assert(!SelfDescribingEvents);
-#if FEATURE_MANAGED_ETW
+#if FEATURE_MANAGED_ETW
fixed (byte* dataPtr = rawManifest)
{
// we don't want the manifest to show up in the event log channels so we specify as keywords
@@ -2760,9 +2791,9 @@ namespace System.Diagnostics.Tracing
while (dataLeft > 0)
{
dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
- if (m_provider != null)
+ if (m_etwProvider != null)
{
- if (!m_provider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
+ if (!m_etwProvider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
{
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
// can fail. If we get this failure on the first chunk try again with something smaller
@@ -3230,7 +3261,7 @@ namespace System.Diagnostics.Tracing
if ((flags & EventManifestOptions.Strict) != 0 && (manifest.Errors.Count > 0 || exception != null))
{
- string msg = String.Empty;
+ string msg = string.Empty;
if (manifest.Errors.Count > 0)
{
bool firstError = true;
@@ -3255,7 +3286,7 @@ namespace System.Diagnostics.Tracing
{
// If the first parameter is (case insensitive) 'relatedActivityId' then skip it.
if (args.Length > 0 && args[0].ParameterType == typeof(Guid) &&
- string.Compare(args[0].Name, "relatedActivityId", StringComparison.OrdinalIgnoreCase) == 0)
+ string.Equals(args[0].Name, "relatedActivityId", StringComparison.OrdinalIgnoreCase))
{
var newargs = new ParameterInfo[args.Length - 1];
Array.Copy(args, 1, newargs, 0, args.Length - 1);
@@ -3465,7 +3496,7 @@ namespace System.Diagnostics.Tracing
/// <param name="method">The method to probe.</param>
/// <returns>The literal value or -1 if the value could not be determined. </returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")]
- static private int GetHelperCallFirstArg(MethodInfo method)
+ private static int GetHelperCallFirstArg(MethodInfo method)
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
// Currently searches for the following pattern
@@ -3612,7 +3643,7 @@ namespace System.Diagnostics.Tracing
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
// send message to debugger without delay
- System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg, Environment.NewLine));
+ System.Diagnostics.Debugger.Log(0, null, string.Format("EventSource Error: {0}{1}", msg, Environment.NewLine));
#endif
// Send it to all listeners.
@@ -3701,7 +3732,10 @@ namespace System.Diagnostics.Tracing
// Dispatching state
internal volatile EventDispatcher m_Dispatchers; // Linked list of code:EventDispatchers we write the data to (we also do ETW specially)
#if FEATURE_MANAGED_ETW
- private volatile OverideEventProvider m_provider; // This hooks up ETW commands to our 'OnEventCommand' callback
+ private volatile OverideEventProvider m_etwProvider; // This hooks up ETW commands to our 'OnEventCommand' callback
+#endif
+#if FEATURE_PERFTRACING
+ private volatile OverideEventProvider m_eventPipeProvider;
#endif
private bool m_completelyInited; // The EventSource constructor has returned without exception.
private Exception m_constructionException; // If there was an exception construction, this is it
@@ -3727,11 +3761,12 @@ namespace System.Diagnostics.Tracing
internal const string s_ActivityStartSuffix = "Start";
internal const string s_ActivityStopSuffix = "Stop";
+ // WARNING: Do not depend upon initialized statics during creation of EventSources, as it is possible for creation of an EventSource to trigger
+ // creation of yet another EventSource. When this happens, these statics may not yet be initialized.
+ // Rather than depending on initialized statics, use lazy initialization to ensure that the statics are initialized exactly when they are needed.
+
// used for generating GUID from eventsource name
- private static readonly byte[] namespaceBytes = new byte[] {
- 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
- 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
- };
+ private static byte[] namespaceBytes;
#endregion
}
@@ -3840,6 +3875,16 @@ namespace System.Diagnostics.Tracing
/// </summary>
public event EventHandler<EventWrittenEventArgs> EventWritten;
+ static EventListener()
+ {
+#if FEATURE_PERFTRACING
+ // Ensure that RuntimeEventSource is initialized so that EventListeners get an opportunity to subscribe to its events.
+ // This is required because RuntimeEventSource never emit events on its own, and thus will never be initialized
+ // in the normal way that EventSources are initialized.
+ GC.KeepAlive(RuntimeEventSource.Log);
+#endif // FEATURE_PERFTRACING
+ }
+
/// <summary>
/// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
/// them on).
@@ -3945,7 +3990,14 @@ namespace System.Diagnostics.Tracing
throw new ArgumentNullException(nameof(eventSource));
}
- eventSource.SendCommand(this, 0, 0, EventCommand.Update, true, level, matchAnyKeyword, arguments);
+ eventSource.SendCommand(this, EventProviderType.None, 0, 0, EventCommand.Update, true, level, matchAnyKeyword, arguments);
+
+#if FEATURE_PERFTRACING
+ if (eventSource.GetType() == typeof(RuntimeEventSource))
+ {
+ EventPipeEventDispatcher.Instance.SendCommand(this, EventCommand.Update, true, level, matchAnyKeyword);
+ }
+#endif // FEATURE_PERFTRACING
}
/// <summary>
/// Disables all events coming from eventSource identified by 'eventSource'.
@@ -3959,7 +4011,14 @@ namespace System.Diagnostics.Tracing
throw new ArgumentNullException(nameof(eventSource));
}
- eventSource.SendCommand(this, 0, 0, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None, null);
+ eventSource.SendCommand(this, EventProviderType.None, 0, 0, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None, null);
+
+#if FEATURE_PERFTRACING
+ if (eventSource.GetType() == typeof(RuntimeEventSource))
+ {
+ EventPipeEventDispatcher.Instance.SendCommand(this, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None);
+ }
+#endif // FEATURE_PERFTRACING
}
/// <summary>
@@ -4033,6 +4092,12 @@ namespace System.Diagnostics.Tracing
if (!s_EventSourceShutdownRegistered)
{
s_EventSourceShutdownRegistered = true;
+#if ES_BUILD_PN
+ AppContext.ProcessExit += DisposeOnShutdown;
+#else
+ AppDomain.CurrentDomain.ProcessExit += DisposeOnShutdown;
+ AppDomain.CurrentDomain.DomainUnload += DisposeOnShutdown;
+#endif
}
@@ -4061,9 +4126,24 @@ namespace System.Diagnostics.Tracing
}
newEventSource.m_id = newIndex;
- // Add every existing dispatcher to the new EventSource
- for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
- newEventSource.AddListener(listener);
+#if DEBUG
+ // Disable validation of EventSource/EventListener connections in case a call to EventSource.AddListener
+ // causes a recursive call into this method.
+ bool previousValue = s_ConnectingEventSourcesAndListener;
+ s_ConnectingEventSourcesAndListener = true;
+ try
+ {
+#endif
+ // Add every existing dispatcher to the new EventSource
+ for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
+ newEventSource.AddListener(listener);
+#if DEBUG
+ }
+ finally
+ {
+ s_ConnectingEventSourcesAndListener = previousValue;
+ }
+#endif
Validate();
}
@@ -4131,6 +4211,11 @@ namespace System.Diagnostics.Tracing
}
}
}
+
+#if FEATURE_PERFTRACING
+ // Remove the listener from the EventPipe dispatcher.
+ EventPipeEventDispatcher.Instance.RemoveEventListener(listenerToRemove);
+#endif // FEATURE_PERFTRACING
}
/// <summary>
@@ -4139,6 +4224,14 @@ namespace System.Diagnostics.Tracing
[Conditional("DEBUG")]
internal static void Validate()
{
+#if DEBUG
+ // Don't run validation code if we're in the middle of modifying the connections between EventSources and EventListeners.
+ if (s_ConnectingEventSourcesAndListener)
+ {
+ return;
+ }
+#endif
+
lock (EventListenersLock)
{
// Get all listeners
@@ -4228,18 +4321,30 @@ namespace System.Diagnostics.Tracing
// is created.
WeakReference[] eventSourcesSnapshot = s_EventSources.ToArray();
- for (int i = 0; i < eventSourcesSnapshot.Length; i++)
+#if DEBUG
+ bool previousValue = s_ConnectingEventSourcesAndListener;
+ s_ConnectingEventSourcesAndListener = true;
+ try
{
- WeakReference eventSourceRef = eventSourcesSnapshot[i];
- EventSource eventSource = eventSourceRef.Target as EventSource;
- if (eventSource != null)
+#endif
+ for (int i = 0; i < eventSourcesSnapshot.Length; i++)
{
- EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
- args.EventSource = eventSource;
- callback(this, args);
+ WeakReference eventSourceRef = eventSourcesSnapshot[i];
+ EventSource eventSource = eventSourceRef.Target as EventSource;
+ if (eventSource != null)
+ {
+ EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
+ args.EventSource = eventSource;
+ callback(this, args);
+ }
}
+#if DEBUG
}
-
+ finally
+ {
+ s_ConnectingEventSourcesAndListener = previousValue;
+ }
+#endif
Validate();
}
finally
@@ -4273,6 +4378,16 @@ namespace System.Diagnostics.Tracing
/// </summary>
private static bool s_CreatingListener = false;
+#if DEBUG
+ /// <summary>
+ /// Used to disable validation of EventSource and EventListener connectivity.
+ /// This is needed when an EventListener is in the middle of being published to all EventSources
+ /// and another EventSource is created as part of the process.
+ /// </summary>
+ [ThreadStatic]
+ private static bool s_ConnectingEventSourcesAndListener = false;
+#endif
+
/// <summary>
/// Used to register AD/Process shutdown callbacks.
/// </summary>
@@ -4293,7 +4408,7 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// Gets the arguments for the callback.
/// </summary>
- public IDictionary<String, String> Arguments { get; internal set; }
+ public IDictionary<string, string> Arguments { get; internal set; }
/// <summary>
/// Enables the event that has the specified identifier.
@@ -4304,7 +4419,7 @@ namespace System.Diagnostics.Tracing
{
if (Command != EventCommand.Enable && Command != EventCommand.Disable)
throw new InvalidOperationException();
- return eventSource.EnableEventForDispatcher(dispatcher, eventId, true);
+ return eventSource.EnableEventForDispatcher(dispatcher, eventProviderType, eventId, true);
}
/// <summary>
@@ -4316,18 +4431,19 @@ namespace System.Diagnostics.Tracing
{
if (Command != EventCommand.Enable && Command != EventCommand.Disable)
throw new InvalidOperationException();
- return eventSource.EnableEventForDispatcher(dispatcher, eventId, false);
+ return eventSource.EnableEventForDispatcher(dispatcher, eventProviderType, eventId, false);
}
#region private
internal EventCommandEventArgs(EventCommand command, IDictionary<string, string> arguments, EventSource eventSource,
- EventListener listener, int perEventSourceSessionId, int etwSessionId, bool enable, EventLevel level, EventKeywords matchAnyKeyword)
+ EventListener listener, EventProviderType eventProviderType, int perEventSourceSessionId, int etwSessionId, bool enable, EventLevel level, EventKeywords matchAnyKeyword)
{
this.Command = command;
this.Arguments = arguments;
this.eventSource = eventSource;
this.listener = listener;
+ this.eventProviderType = eventProviderType;
this.perEventSourceSessionId = perEventSourceSessionId;
this.etwSessionId = etwSessionId;
this.enable = enable;
@@ -4337,6 +4453,7 @@ namespace System.Diagnostics.Tracing
internal EventSource eventSource;
internal EventDispatcher dispatcher;
+ internal EventProviderType eventProviderType;
// These are the arguments of sendCommand and are only used for deferring commands until after we are fully initialized.
internal EventListener listener;
@@ -4401,7 +4518,20 @@ namespace System.Diagnostics.Tracing
/// </summary>
public Guid ActivityId
{
- get { return EventSource.CurrentThreadActivityId; }
+ get
+ {
+ Guid activityId = m_activityId;
+ if (activityId == Guid.Empty)
+ {
+ activityId = EventSource.CurrentThreadActivityId;
+ }
+
+ return activityId;
+ }
+ internal set
+ {
+ m_activityId = value;
+ }
}
/// <summary>
@@ -4416,7 +4546,7 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// Gets the payload for the event.
/// </summary>
- public ReadOnlyCollection<Object> Payload { get; internal set; }
+ public ReadOnlyCollection<object> Payload { get; internal set; }
/// <summary>
/// Gets the payload argument names.
@@ -4567,15 +4697,47 @@ namespace System.Diagnostics.Tracing
}
}
+ /// <summary>
+ /// Gets the identifier for the OS thread that wrote the event.
+ /// </summary>
+ public long OSThreadId
+ {
+ get
+ {
+ if (!m_osThreadId.HasValue)
+ {
+ m_osThreadId = (long)RuntimeThread.CurrentOSThreadId;
+ }
+
+ return m_osThreadId.Value;
+ }
+ internal set
+ {
+ m_osThreadId = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets a UTC DateTime that specifies when the event was written.
+ /// </summary>
+ public DateTime TimeStamp
+ {
+ get;
+ internal set;
+ }
+
#region private
internal EventWrittenEventArgs(EventSource eventSource)
{
m_eventSource = eventSource;
+ TimeStamp = DateTime.UtcNow;
}
private string m_message;
private string m_eventName;
private EventSource m_eventSource;
private ReadOnlyCollection<string> m_payloadNames;
+ private Guid m_activityId;
+ private long? m_osThreadId;
internal EventTags m_tags;
internal EventOpcode m_opcode;
internal EventLevel m_level;
@@ -5215,7 +5377,7 @@ namespace System.Diagnostics.Tracing
templates.Append(" length=\"").Append(name).Append("Size\"");
}
// ETW does not support 64-bit value maps, so we don't specify these as ETW maps
- if (type.IsEnum() && Enum.GetUnderlyingType(type) != typeof(UInt64) && Enum.GetUnderlyingType(type) != typeof(Int64))
+ if (type.IsEnum() && Enum.GetUnderlyingType(type) != typeof(ulong) && Enum.GetUnderlyingType(type) != typeof(long))
{
templates.Append(" map=\"").Append(type.Name).Append("\"");
if (mapsTab == null)
@@ -5412,29 +5574,38 @@ namespace System.Diagnostics.Tracing
// write out each enum value
FieldInfo[] staticFields = enumType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
+ bool anyValuesWritten = false;
foreach (FieldInfo staticField in staticFields)
{
object constantValObj = staticField.GetRawConstantValue();
+
if (constantValObj != null)
{
- long hexValue;
- if (constantValObj is int)
- hexValue = ((int)constantValObj);
- else if (constantValObj is long)
- hexValue = ((long)constantValObj);
- else
- continue;
+ ulong hexValue;
+ if (constantValObj is ulong)
+ hexValue = (ulong)constantValObj; // This is the only integer type that can't be represented by a long.
+ else
+ hexValue = (ulong) Convert.ToInt64(constantValObj); // Handles all integer types except ulong.
// ETW requires all bitmap values to be powers of 2. Skip the ones that are not.
// TODO: Warn people about the dropping of values.
if (isbitmap && ((hexValue & (hexValue - 1)) != 0 || hexValue == 0))
continue;
-
sb.Append(" <map value=\"0x").Append(hexValue.ToString("x", CultureInfo.InvariantCulture)).Append("\"");
WriteMessageAttrib(sb, "map", enumType.Name + "." + staticField.Name, staticField.Name);
sb.Append("/>").AppendLine();
+ anyValuesWritten = true;
}
}
+
+ // the OS requires that bitmaps and valuemaps have at least one value or it reject the whole manifest.
+ // To avoid that put a 'None' entry if there are no other values.
+ if (!anyValuesWritten)
+ {
+ sb.Append(" <map value=\"0x0\"");
+ WriteMessageAttrib(sb, "map", enumType.Name + "." + "None", "None");
+ sb.Append("/>").AppendLine();
+ }
sb.Append(" </").Append(mapKind).Append(">").AppendLine();
}
sb.Append(" </maps>").AppendLine();
@@ -5778,7 +5949,7 @@ namespace System.Diagnostics.Tracing
int leftBracket = i;
i++;
int argNum = 0;
- while (i < eventMessage.Length && Char.IsDigit(eventMessage[i]))
+ while (i < eventMessage.Length && char.IsDigit(eventMessage[i]))
{
argNum = argNum * 10 + eventMessage[i] - '0';
i++;
@@ -5904,4 +6075,3 @@ namespace System.Diagnostics.Tracing
#endregion
}
-
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs
index d34f80eb5..9bbebc79e 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs
@@ -38,6 +38,6 @@ namespace System.Diagnostics.Tracing
int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId);
// Define an EventPipeEvent handle.
- unsafe IntPtr DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
+ unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs
index 1b3ca8004..6f2eb9ba2 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs
@@ -30,10 +30,10 @@ namespace System.Diagnostics.Tracing.Internal
if (fmt != null)
return string.Format(fmt, args);
- string sargs = String.Empty;
+ string sargs = string.Empty;
foreach(var arg in args)
{
- if (sargs != String.Empty)
+ if (sargs != string.Empty)
sargs += ", ";
sargs += arg.ToString();
}
@@ -301,7 +301,7 @@ namespace Microsoft.Reflection
else if (type == typeof(float)) return TypeCode.Single;
else if (type == typeof(double)) return TypeCode.Double;
else if (type == typeof(DateTime)) return TypeCode.DateTime;
- else if (type == (typeof(Decimal))) return TypeCode.Decimal;
+ else if (type == (typeof(decimal))) return TypeCode.Decimal;
else return TypeCode.Object;
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs
index 1444c267c..11c18a260 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs
@@ -143,6 +143,45 @@ namespace System.Diagnostics.Tracing
}
}
+ internal unsafe void AddNullTerminatedString(string value)
+ {
+ // Treat null strings as empty strings.
+ if (value == null)
+ {
+ value = string.Empty;
+ }
+
+ // Calculate the size of the string including the trailing NULL char.
+ // Don't use value.Length here because string allows for embedded NULL characters.
+ int nullCharIndex = value.IndexOf((char)0);
+ if (nullCharIndex < 0)
+ {
+ nullCharIndex = value.Length;
+ }
+ int size = (nullCharIndex + 1) * 2;
+
+ if (this.bufferNesting != 0)
+ {
+ this.EnsureBuffer(size);
+ }
+
+ if (this.bufferNesting == 0)
+ {
+ this.ScalarsEnd();
+ this.PinArray(value, size);
+ }
+ else
+ {
+ var oldPos = this.bufferPos;
+ this.bufferPos = checked(this.bufferPos + size);
+ this.EnsureBuffer();
+ fixed (void* p = value)
+ {
+ Marshal.Copy((IntPtr)p, buffer, oldPos, size);
+ }
+ }
+ }
+
internal void AddBinary(Array value, int size)
{
this.AddArray(value, size, 1);
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
index 30a941195..3febe6ff9 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
@@ -144,7 +144,7 @@ namespace System.Diagnostics.Tracing
position++;
}
- value = default(object);
+ value = default;
return false;
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
index 865082f76..2d7155080 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
@@ -314,7 +314,7 @@ namespace System.Diagnostics.Tracing
private State state;
private string eventName;
- static internal Guid s_empty;
+ internal static Guid s_empty;
#endregion
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs
index 9c7c6369e..f15373475 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs
@@ -135,13 +135,11 @@ namespace System.Diagnostics.Tracing
{
throw new NotSupportedException(SR.EventSource_NotSupportedArrayOfBinary);
}
-#if !BROKEN_UNTIL_M3
if (coreType == (int)TraceLoggingDataType.Utf16String ||
coreType == (int)TraceLoggingDataType.MbcsString)
{
throw new NotSupportedException(SR.EventSource_NotSupportedArrayOfNullTerminatedString);
}
-#endif
}
if (((int)this.tags & 0xfffffff) != 0)
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs
index 3e5997bc9..2a7113e5d 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs
@@ -21,7 +21,7 @@ namespace System.Diagnostics.Tracing
/// </typeparam>
internal sealed class InvokeTypeInfo : TraceLoggingTypeInfo
{
- private readonly PropertyAnalysis[] properties;
+ internal readonly PropertyAnalysis[] properties;
public InvokeTypeInfo(
Type type,
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
index 668043ae6..a7daf5e75 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Concurrent;
using Interlocked = System.Threading.Interlocked;
#if ES_BUILD_STANDALONE
@@ -75,5 +76,50 @@ namespace System.Diagnostics.Tracing
}
return result;
}
+
+#if FEATURE_PERFTRACING
+ public IntPtr GetOrCreateEventHandle(EventProvider provider, TraceLoggingEventHandleTable eventHandleTable, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
+ {
+ IntPtr eventHandle;
+ if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero)
+ {
+ lock (eventHandleTable)
+ {
+ if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero)
+ {
+ byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(
+ descriptor.EventId,
+ name,
+ (EventKeywords)descriptor.Keywords,
+ (EventLevel)descriptor.Level,
+ descriptor.Version,
+ eventTypes);
+ uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0;
+
+ unsafe
+ {
+ fixed (byte* pMetadataBlob = metadataBlob)
+ {
+ // Define the event.
+ eventHandle = provider.m_eventProvider.DefineEventHandle(
+ (uint)descriptor.EventId,
+ name,
+ descriptor.Keywords,
+ descriptor.Version,
+ descriptor.Level,
+ pMetadataBlob,
+ metadataLength);
+ }
+ }
+
+ // Cache the event handle.
+ eventHandleTable.SetEventHandle(descriptor.EventId, eventHandle);
+ }
+ }
+ }
+
+ return eventHandle;
+ }
+#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
index ae6088849..daa6d9736 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
@@ -40,33 +40,33 @@ namespace System.Diagnostics.Tracing
public struct Scalar
{
[FieldOffset(0)]
- public Boolean AsBoolean;
+ public bool AsBoolean;
[FieldOffset(0)]
- public Byte AsByte;
+ public byte AsByte;
[FieldOffset(0)]
- public SByte AsSByte;
+ public sbyte AsSByte;
[FieldOffset(0)]
- public Char AsChar;
+ public char AsChar;
[FieldOffset(0)]
- public Int16 AsInt16;
+ public short AsInt16;
[FieldOffset(0)]
- public UInt16 AsUInt16;
+ public ushort AsUInt16;
[FieldOffset(0)]
- public Int32 AsInt32;
+ public int AsInt32;
[FieldOffset(0)]
- public UInt32 AsUInt32;
+ public uint AsUInt32;
[FieldOffset(0)]
- public Int64 AsInt64;
+ public long AsInt64;
[FieldOffset(0)]
- public UInt64 AsUInt64;
+ public ulong AsUInt64;
[FieldOffset(0)]
public IntPtr AsIntPtr;
[FieldOffset(0)]
public UIntPtr AsUIntPtr;
[FieldOffset(0)]
- public Single AsSingle;
+ public float AsSingle;
[FieldOffset(0)]
- public Double AsDouble;
+ public double AsDouble;
[FieldOffset(0)]
public Guid AsGuid;
[FieldOffset(0)]
@@ -76,7 +76,7 @@ namespace System.Diagnostics.Tracing
[FieldOffset(0)]
public TimeSpan AsTimeSpan;
[FieldOffset(0)]
- public Decimal AsDecimal;
+ public decimal AsDecimal;
}
// Anything not covered by the Scalar union gets stored in this reference.
@@ -87,7 +87,7 @@ namespace System.Diagnostics.Tracing
private PropertyValue(object value)
{
_reference = value;
- _scalar = default(Scalar);
+ _scalar = default;
_scalarLength = 0;
}
@@ -98,47 +98,47 @@ namespace System.Diagnostics.Tracing
_scalarLength = scalarLength;
}
- private PropertyValue(Boolean value) : this(new Scalar() { AsBoolean = value }, sizeof(Boolean)) { }
- private PropertyValue(Byte value) : this(new Scalar() { AsByte = value }, sizeof(Byte)) { }
- private PropertyValue(SByte value) : this(new Scalar() { AsSByte = value }, sizeof(SByte)) { }
- private PropertyValue(Char value) : this(new Scalar() { AsChar = value }, sizeof(Char)) { }
- private PropertyValue(Int16 value) : this(new Scalar() { AsInt16 = value }, sizeof(Int16)) { }
- private PropertyValue(UInt16 value) : this(new Scalar() { AsUInt16 = value }, sizeof(UInt16)) { }
- private PropertyValue(Int32 value) : this(new Scalar() { AsInt32 = value }, sizeof(Int32)) { }
- private PropertyValue(UInt32 value) : this(new Scalar() { AsUInt32 = value }, sizeof(UInt32)) { }
- private PropertyValue(Int64 value) : this(new Scalar() { AsInt64 = value }, sizeof(Int64)) { }
- private PropertyValue(UInt64 value) : this(new Scalar() { AsUInt64 = value }, sizeof(UInt64)) { }
+ private PropertyValue(bool value) : this(new Scalar() { AsBoolean = value }, sizeof(bool)) { }
+ private PropertyValue(byte value) : this(new Scalar() { AsByte = value }, sizeof(byte)) { }
+ private PropertyValue(sbyte value) : this(new Scalar() { AsSByte = value }, sizeof(sbyte)) { }
+ private PropertyValue(char value) : this(new Scalar() { AsChar = value }, sizeof(char)) { }
+ private PropertyValue(short value) : this(new Scalar() { AsInt16 = value }, sizeof(short)) { }
+ private PropertyValue(ushort value) : this(new Scalar() { AsUInt16 = value }, sizeof(ushort)) { }
+ private PropertyValue(int value) : this(new Scalar() { AsInt32 = value }, sizeof(int)) { }
+ private PropertyValue(uint value) : this(new Scalar() { AsUInt32 = value }, sizeof(uint)) { }
+ private PropertyValue(long value) : this(new Scalar() { AsInt64 = value }, sizeof(long)) { }
+ private PropertyValue(ulong value) : this(new Scalar() { AsUInt64 = value }, sizeof(ulong)) { }
private PropertyValue(IntPtr value) : this(new Scalar() { AsIntPtr = value }, sizeof(IntPtr)) { }
private PropertyValue(UIntPtr value) : this(new Scalar() { AsUIntPtr = value }, sizeof(UIntPtr)) { }
- private PropertyValue(Single value) : this(new Scalar() { AsSingle = value }, sizeof(Single)) { }
- private PropertyValue(Double value) : this(new Scalar() { AsDouble = value }, sizeof(Double)) { }
+ private PropertyValue(float value) : this(new Scalar() { AsSingle = value }, sizeof(float)) { }
+ private PropertyValue(double value) : this(new Scalar() { AsDouble = value }, sizeof(double)) { }
private PropertyValue(Guid value) : this(new Scalar() { AsGuid = value }, sizeof(Guid)) { }
private PropertyValue(DateTime value) : this(new Scalar() { AsDateTime = value }, sizeof(DateTime)) { }
private PropertyValue(DateTimeOffset value) : this(new Scalar() { AsDateTimeOffset = value }, sizeof(DateTimeOffset)) { }
private PropertyValue(TimeSpan value) : this(new Scalar() { AsTimeSpan = value }, sizeof(TimeSpan)) { }
- private PropertyValue(Decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(Decimal)) { }
+ private PropertyValue(decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(decimal)) { }
public static Func<object, PropertyValue> GetFactory(Type type)
{
- if (type == typeof(Boolean)) return value => new PropertyValue((Boolean)value);
- if (type == typeof(Byte)) return value => new PropertyValue((Byte)value);
- if (type == typeof(SByte)) return value => new PropertyValue((SByte)value);
- if (type == typeof(Char)) return value => new PropertyValue((Char)value);
- if (type == typeof(Int16)) return value => new PropertyValue((Int16)value);
- if (type == typeof(UInt16)) return value => new PropertyValue((UInt16)value);
- if (type == typeof(Int32)) return value => new PropertyValue((Int32)value);
- if (type == typeof(UInt32)) return value => new PropertyValue((UInt32)value);
- if (type == typeof(Int64)) return value => new PropertyValue((Int64)value);
- if (type == typeof(UInt64)) return value => new PropertyValue((UInt64)value);
+ if (type == typeof(bool)) return value => new PropertyValue((bool)value);
+ if (type == typeof(byte)) return value => new PropertyValue((byte)value);
+ if (type == typeof(sbyte)) return value => new PropertyValue((sbyte)value);
+ if (type == typeof(char)) return value => new PropertyValue((char)value);
+ if (type == typeof(short)) return value => new PropertyValue((short)value);
+ if (type == typeof(ushort)) return value => new PropertyValue((ushort)value);
+ if (type == typeof(int)) return value => new PropertyValue((int)value);
+ if (type == typeof(uint)) return value => new PropertyValue((uint)value);
+ if (type == typeof(long)) return value => new PropertyValue((long)value);
+ if (type == typeof(ulong)) return value => new PropertyValue((ulong)value);
if (type == typeof(IntPtr)) return value => new PropertyValue((IntPtr)value);
if (type == typeof(UIntPtr)) return value => new PropertyValue((UIntPtr)value);
- if (type == typeof(Single)) return value => new PropertyValue((Single)value);
- if (type == typeof(Double)) return value => new PropertyValue((Double)value);
+ if (type == typeof(float)) return value => new PropertyValue((float)value);
+ if (type == typeof(double)) return value => new PropertyValue((double)value);
if (type == typeof(Guid)) return value => new PropertyValue((Guid)value);
if (type == typeof(DateTime)) return value => new PropertyValue((DateTime)value);
if (type == typeof(DateTimeOffset)) return value => new PropertyValue((DateTimeOffset)value);
if (type == typeof(TimeSpan)) return value => new PropertyValue((TimeSpan)value);
- if (type == typeof(Decimal)) return value => new PropertyValue((Decimal)value);
+ if (type == typeof(decimal)) return value => new PropertyValue((decimal)value);
return value => new PropertyValue(value);
}
@@ -249,25 +249,25 @@ namespace System.Diagnostics.Tracing
if (type.GetTypeInfo().IsEnum)
type = Enum.GetUnderlyingType(type);
- if (type == typeof(Boolean)) { var f = (Func<TContainer, Boolean>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Byte)) { var f = (Func<TContainer, Byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(SByte)) { var f = (Func<TContainer, SByte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Char)) { var f = (Func<TContainer, Char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Int16)) { var f = (Func<TContainer, Int16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(UInt16)) { var f = (Func<TContainer, UInt16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Int32)) { var f = (Func<TContainer, Int32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(UInt32)) { var f = (Func<TContainer, UInt32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Int64)) { var f = (Func<TContainer, Int64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(UInt64)) { var f = (Func<TContainer, UInt64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(bool)) { var f = (Func<TContainer, bool>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(byte)) { var f = (Func<TContainer, byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(sbyte)) { var f = (Func<TContainer, sbyte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(char)) { var f = (Func<TContainer, char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(short)) { var f = (Func<TContainer, short>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(ushort)) { var f = (Func<TContainer, ushort>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(int)) { var f = (Func<TContainer, int>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(uint)) { var f = (Func<TContainer, uint>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(long)) { var f = (Func<TContainer, long>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(ulong)) { var f = (Func<TContainer, ulong>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Single)) { var f = (Func<TContainer, Single>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Double)) { var f = (Func<TContainer, Double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(float)) { var f = (Func<TContainer, float>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(double)) { var f = (Func<TContainer, double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Decimal)) { var f = (Func<TContainer, Decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(decimal)) { var f = (Func<TContainer, decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
return container => new PropertyValue(property.GetValue(container.ReferenceValue));
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
index 9b58d8251..e0a937479 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
@@ -73,20 +73,20 @@ namespace System.Diagnostics.Tracing
collector.AddScalar(value);
}
- public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(Boolean), Statics.Format8, TraceLoggingDataType.Boolean8); }
- public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(Byte), Statics.Format8, TraceLoggingDataType.UInt8); }
- public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(SByte), Statics.Format8, TraceLoggingDataType.Int8); }
- public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(Char), Statics.Format16, TraceLoggingDataType.Char16); }
- public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(Int16), Statics.Format16, TraceLoggingDataType.Int16); }
- public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(UInt16), Statics.Format16, TraceLoggingDataType.UInt16); }
- public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(Int32), Statics.Format32, TraceLoggingDataType.Int32); }
- public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(UInt32), Statics.Format32, TraceLoggingDataType.UInt32); }
- public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(Int64), Statics.Format64, TraceLoggingDataType.Int64); }
- public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(UInt64), Statics.Format64, TraceLoggingDataType.UInt64); }
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(bool), Statics.Format8, TraceLoggingDataType.Boolean8); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(byte), Statics.Format8, TraceLoggingDataType.UInt8); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(sbyte), Statics.Format8, TraceLoggingDataType.Int8); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(char), Statics.Format16, TraceLoggingDataType.Char16); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(short), Statics.Format16, TraceLoggingDataType.Int16); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(ushort), Statics.Format16, TraceLoggingDataType.UInt16); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(int), Statics.Format32, TraceLoggingDataType.Int32); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(uint), Statics.Format32, TraceLoggingDataType.UInt32); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(long), Statics.Format64, TraceLoggingDataType.Int64); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(ulong), Statics.Format64, TraceLoggingDataType.UInt64); }
public static TraceLoggingTypeInfo IntPtr() { return new ScalarTypeInfo(typeof(IntPtr), Statics.FormatPtr, Statics.IntPtrType); }
public static TraceLoggingTypeInfo UIntPtr() { return new ScalarTypeInfo(typeof(UIntPtr), Statics.FormatPtr, Statics.UIntPtrType); }
- public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(Single), Statics.Format32, TraceLoggingDataType.Float); }
- public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(Double), Statics.Format64, TraceLoggingDataType.Double); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(float), Statics.Format32, TraceLoggingDataType.Float); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(double), Statics.Format64, TraceLoggingDataType.Double); }
public static TraceLoggingTypeInfo Guid() { return new ScalarTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid); }
}
@@ -122,21 +122,21 @@ namespace System.Diagnostics.Tracing
collector.AddArray(value, elementSize);
}
- public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(Boolean[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(Boolean)); }
- public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(Byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(Byte)); }
- public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(SByte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(SByte)); }
- public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(Char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(Char)); }
- public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(Int16[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(Int16)); }
- public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(UInt16[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(UInt16)); }
- public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(Int32[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(Int32)); }
- public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(UInt32[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(UInt32)); }
- public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(Int64[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(Int64)); }
- public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(UInt64[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(UInt64)); }
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(bool[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(bool)); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(byte)); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(sbyte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(sbyte)); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(char)); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(short[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(short)); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(ushort[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(ushort)); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(int[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(int)); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(uint[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(uint)); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(long[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(long)); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(ulong[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(ulong)); }
public static TraceLoggingTypeInfo IntPtr() { return new ScalarArrayTypeInfo(typeof(IntPtr[]), Statics.FormatPtr, Statics.IntPtrType, System.IntPtr.Size); }
public static TraceLoggingTypeInfo UIntPtr() { return new ScalarArrayTypeInfo(typeof(UIntPtr[]), Statics.FormatPtr, Statics.UIntPtrType, System.IntPtr.Size); }
- public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(Single[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(Single)); }
- public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(Double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(Double)); }
- public unsafe static TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(float[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(float)); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(double)); }
+ public static unsafe TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
}
/// <summary>
@@ -151,12 +151,12 @@ namespace System.Diagnostics.Tracing
string name,
EventFieldFormat format)
{
- collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.CountedUtf16String, format));
+ collector.AddNullTerminatedString(name, Statics.MakeDataType(TraceLoggingDataType.Utf16String, format));
}
public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddBinary((string)value.ReferenceValue);
+ collector.AddNullTerminatedString((string)value.ReferenceValue);
}
public override object GetData(object value)
@@ -243,11 +243,11 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
- /// TraceLogging: Type handler for Decimal. (Note: not full-fidelity, exposed as Double.)
+ /// TraceLogging: Type handler for decimal. (Note: not full-fidelity, exposed as Double.)
/// </summary>
internal sealed class DecimalTypeInfo : TraceLoggingTypeInfo
{
- public DecimalTypeInfo() : base(typeof(Decimal)) { }
+ public DecimalTypeInfo() : base(typeof(decimal)) { }
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs
index 05539ab4f..0c2167213 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs
@@ -548,51 +548,51 @@ namespace System.Diagnostics.Tracing
else if (dataType.IsArray)
{
var elementType = dataType.GetElementType();
- if (elementType == typeof(Boolean))
+ if (elementType == typeof(bool))
{
result = ScalarArrayTypeInfo.Boolean();
}
- else if (elementType == typeof(Byte))
+ else if (elementType == typeof(byte))
{
result = ScalarArrayTypeInfo.Byte();
}
- else if (elementType == typeof(SByte))
+ else if (elementType == typeof(sbyte))
{
result = ScalarArrayTypeInfo.SByte();
}
- else if (elementType == typeof(Int16))
+ else if (elementType == typeof(short))
{
result = ScalarArrayTypeInfo.Int16();
}
- else if (elementType == typeof(UInt16))
+ else if (elementType == typeof(ushort))
{
result = ScalarArrayTypeInfo.UInt16();
}
- else if (elementType == typeof(Int32))
+ else if (elementType == typeof(int))
{
result = ScalarArrayTypeInfo.Int32();
}
- else if (elementType == typeof(UInt32))
+ else if (elementType == typeof(uint))
{
result = ScalarArrayTypeInfo.UInt32();
}
- else if (elementType == typeof(Int64))
+ else if (elementType == typeof(long))
{
result = ScalarArrayTypeInfo.Int64();
}
- else if (elementType == typeof(UInt64))
+ else if (elementType == typeof(ulong))
{
result = ScalarArrayTypeInfo.UInt64();
}
- else if (elementType == typeof(Char))
+ else if (elementType == typeof(char))
{
result = ScalarArrayTypeInfo.Char();
}
- else if (elementType == typeof(Double))
+ else if (elementType == typeof(double))
{
result = ScalarArrayTypeInfo.Double();
}
- else if (elementType == typeof(Single))
+ else if (elementType == typeof(float))
{
result = ScalarArrayTypeInfo.Single();
}
@@ -618,55 +618,55 @@ namespace System.Diagnostics.Tracing
if (Statics.IsEnum(dataType))
dataType = Enum.GetUnderlyingType(dataType);
- if (dataType == typeof(String))
+ if (dataType == typeof(string))
{
result = new StringTypeInfo();
}
- else if (dataType == typeof(Boolean))
+ else if (dataType == typeof(bool))
{
result = ScalarTypeInfo.Boolean();
}
- else if (dataType == typeof(Byte))
+ else if (dataType == typeof(byte))
{
result = ScalarTypeInfo.Byte();
}
- else if (dataType == typeof(SByte))
+ else if (dataType == typeof(sbyte))
{
result = ScalarTypeInfo.SByte();
}
- else if (dataType == typeof(Int16))
+ else if (dataType == typeof(short))
{
result = ScalarTypeInfo.Int16();
}
- else if (dataType == typeof(UInt16))
+ else if (dataType == typeof(ushort))
{
result = ScalarTypeInfo.UInt16();
}
- else if (dataType == typeof(Int32))
+ else if (dataType == typeof(int))
{
result = ScalarTypeInfo.Int32();
}
- else if (dataType == typeof(UInt32))
+ else if (dataType == typeof(uint))
{
result = ScalarTypeInfo.UInt32();
}
- else if (dataType == typeof(Int64))
+ else if (dataType == typeof(long))
{
result = ScalarTypeInfo.Int64();
}
- else if (dataType == typeof(UInt64))
+ else if (dataType == typeof(ulong))
{
result = ScalarTypeInfo.UInt64();
}
- else if (dataType == typeof(Char))
+ else if (dataType == typeof(char))
{
result = ScalarTypeInfo.Char();
}
- else if (dataType == typeof(Double))
+ else if (dataType == typeof(double))
{
result = ScalarTypeInfo.Double();
}
- else if (dataType == typeof(Single))
+ else if (dataType == typeof(float))
{
result = ScalarTypeInfo.Single();
}
@@ -674,7 +674,7 @@ namespace System.Diagnostics.Tracing
{
result = new DateTimeTypeInfo();
}
- else if (dataType == typeof(Decimal))
+ else if (dataType == typeof(decimal))
{
result = new DecimalTypeInfo();
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs
index 04a047fb3..f6d0a59aa 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs
@@ -85,6 +85,17 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
+ /// Adds a null-terminated String value to the event payload.
+ /// </summary>
+ /// <param name="value">
+ /// Value to be added. A null value is treated as a zero-length string.
+ /// </param>
+ public void AddNullTerminatedString(string value)
+ {
+ DataCollector.ThreadInstance.AddNullTerminatedString(value);
+ }
+
+ /// <summary>
/// Adds a counted String value to the event payload.
/// </summary>
/// <param name="value">
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
index 4348df7d6..0553f9899 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
@@ -47,6 +47,10 @@ namespace System.Diagnostics.Tracing
private byte[] providerMetadata;
#endif
+#if FEATURE_PERFTRACING
+ private readonly TraceLoggingEventHandleTable m_eventHandleTable = new TraceLoggingEventHandleTable();
+#endif
+
/// <summary>
/// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
/// </summary>
@@ -431,15 +435,22 @@ namespace System.Diagnostics.Tracing
identity = nameInfo.identity;
EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
+#if FEATURE_PERFTRACING
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
+ Debug.Assert(eventHandle != IntPtr.Zero);
+#else
+ IntPtr eventHandle = IntPtr.Zero;
+#endif
+
var pinCount = eventTypes.pinCount;
var scratch = stackalloc byte[eventTypes.scratchSize];
var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
for(int i = 0; i < eventTypes.dataCount + 3; i++)
- descriptors[i] = default(EventData);
+ descriptors[i] = default;
var pins = stackalloc GCHandle[pinCount];
for (int i = 0; i < pinCount; i++)
- pins[i] = default(GCHandle);
+ pins[i] = default;
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -472,6 +483,7 @@ namespace System.Diagnostics.Tracing
this.WriteEventRaw(
eventName,
ref descriptor,
+ eventHandle,
activityID,
childActivityID,
(int)(DataCollector.ThreadInstance.Finish() - descriptors),
@@ -538,12 +550,19 @@ namespace System.Diagnostics.Tracing
return;
}
+#if FEATURE_PERFTRACING
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
+ Debug.Assert(eventHandle != IntPtr.Zero);
+#else
+ IntPtr eventHandle = IntPtr.Zero;
+#endif
+
// We make a descriptor for each EventData, and because we morph strings to counted strings
// we may have 2 for each arg, so we allocate enough for this.
var descriptorsLength = eventTypes.dataCount + eventTypes.typeInfos.Length * 2 + 3;
var descriptors = stackalloc EventData[descriptorsLength];
for(int i = 0; i < descriptorsLength; i++)
- descriptors[i] = default(EventData);
+ descriptors[i] = default;
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -557,35 +576,20 @@ namespace System.Diagnostics.Tracing
for (int i = 0; i < eventTypes.typeInfos.Length; i++)
{
- // Until M3, we need to morph strings to a counted representation
- // When TDH supports null terminated strings, we can remove this.
- if (eventTypes.typeInfos[i].DataType == typeof(string))
- {
- // Write out the size of the string
- descriptors[numDescrs].DataPointer = (IntPtr) (&descriptors[numDescrs + 1].m_Size);
- descriptors[numDescrs].m_Size = 2;
- numDescrs++;
-
- descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
- descriptors[numDescrs].m_Size = data[i].m_Size - 2; // Remove the null terminator
- numDescrs++;
- }
- else
- {
- descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
- descriptors[numDescrs].m_Size = data[i].m_Size;
+ descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
+ descriptors[numDescrs].m_Size = data[i].m_Size;
- // old conventions for bool is 4 bytes, but meta-data assumes 1.
- if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool))
- descriptors[numDescrs].m_Size = 1;
+ // old conventions for bool is 4 bytes, but meta-data assumes 1.
+ if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool))
+ descriptors[numDescrs].m_Size = 1;
- numDescrs++;
- }
+ numDescrs++;
}
this.WriteEventRaw(
eventName,
ref descriptor,
+ eventHandle,
activityID,
childActivityID,
numDescrs,
@@ -615,16 +619,23 @@ namespace System.Diagnostics.Tracing
return;
}
+#if FEATURE_PERFTRACING
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
+ Debug.Assert(eventHandle != IntPtr.Zero);
+#else
+ IntPtr eventHandle = IntPtr.Zero;
+#endif
+
#if FEATURE_MANAGED_ETW
var pinCount = eventTypes.pinCount;
var scratch = stackalloc byte[eventTypes.scratchSize];
var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
for(int i=0; i<eventTypes.dataCount + 3; i++)
- descriptors[i] = default(EventData);
+ descriptors[i] = default;
var pins = stackalloc GCHandle[pinCount];
for (int i = 0; i < pinCount; i++)
- pins[i] = default(GCHandle);
+ pins[i] = default;
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -637,7 +648,7 @@ namespace System.Diagnostics.Tracing
#endif // FEATURE_MANAGED_ETW
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
- System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
+ System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
#endif
EventOpcode opcode = (EventOpcode)descriptor.Opcode;
@@ -677,6 +688,7 @@ namespace System.Diagnostics.Tracing
this.WriteEventRaw(
eventName,
ref descriptor,
+ eventHandle,
pActivityId,
pRelatedActivityId,
(int)(DataCollector.ThreadInstance.Finish() - descriptors),
@@ -687,7 +699,7 @@ namespace System.Diagnostics.Tracing
if (m_Dispatchers != null)
{
var eventData = (EventPayload)(eventTypes.typeInfos[0].GetData(data));
- WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, eventData);
+ WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, pRelatedActivityId, eventData);
}
}
@@ -716,7 +728,7 @@ namespace System.Diagnostics.Tracing
}
}
- private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid* pActivityId, EventPayload payload)
+ private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid* pActivityId, Guid* pChildActivityId, EventPayload payload)
{
EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
eventCallbackArgs.EventName = eventName;
@@ -728,7 +740,9 @@ namespace System.Diagnostics.Tracing
// Self described events do not have an id attached. We mark it internally with -1.
eventCallbackArgs.EventId = -1;
if (pActivityId != null)
- eventCallbackArgs.RelatedActivityId = *pActivityId;
+ eventCallbackArgs.ActivityId = *pActivityId;
+ if (pChildActivityId != null)
+ eventCallbackArgs.RelatedActivityId = *pChildActivityId;
if (payload != null)
{
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs
index 3c775a3ce..8887714fd 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs
@@ -25,6 +25,9 @@ namespace System.Diagnostics.Tracing
public class TraceLoggingEventTypes
{
internal readonly TraceLoggingTypeInfo[] typeInfos;
+#if FEATURE_PERFTRACING
+ internal readonly string[] paramNames;
+#endif
internal readonly string name;
internal readonly EventTags tags;
internal readonly byte level;
@@ -98,6 +101,9 @@ namespace System.Diagnostics.Tracing
}
this.typeInfos = MakeArray(paramInfos);
+#if FEATURE_PERFTRACING
+ this.paramNames = MakeParamNameArray(paramInfos);
+#endif
this.name = name;
this.tags = tags;
this.level = Statics.DefaultLevel;
@@ -248,5 +254,19 @@ namespace System.Diagnostics.Tracing
return (TraceLoggingTypeInfo[])typeInfos.Clone(); ;
}
+
+#if FEATURE_PERFTRACING
+ private static string[] MakeParamNameArray(
+ System.Reflection.ParameterInfo[] paramInfos)
+ {
+ string[] paramNames = new string[paramInfos.Length];
+ for (int i = 0; i < paramNames.Length; i++)
+ {
+ paramNames[i] = paramInfos[i].Name;
+ }
+
+ return paramNames;
+ }
+#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs
index 1db1a28c9..b5b199dbc 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs
@@ -192,22 +192,43 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
+ /// Adds a null-terminated string field to an event.
+ /// Compatible with core types: Utf16String, MbcsString.
+ /// Compatible with dataCollector method: AddNullTerminatedString(string).
+ /// </summary>
+ /// <param name="name">
+ /// The name to use for the added field. This value must not be null.
+ /// </param>
+ /// <param name="type">
+ /// The type code for the added field. This must be a null-terminated string type.
+ /// </param>
+ public void AddNullTerminatedString(string name, TraceLoggingDataType type)
+ {
+ switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
+ {
+ case TraceLoggingDataType.Utf16String:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(type));
+ }
+
+ this.impl.AddNonscalar();
+ this.AddField(new FieldMetadata(name, type, this.Tags, this.BeginningBufferedArray));
+ }
+
+ /// <summary>
/// Adds an array field to an event.
/// </summary>
/// <param name="name">
/// The name to use for the added field. This value must not be null.
/// </param>
/// <param name="type">
- /// The type code for the added field. This must be a fixed-size type
- /// or a string type. In the case of a string type, this adds an array
- /// of characters, not an array of strings.
+ /// The type code for the added field. This must be a fixed-size type.
/// </param>
public void AddArray(string name, TraceLoggingDataType type)
{
switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
{
- case TraceLoggingDataType.Utf16String:
- case TraceLoggingDataType.MbcsString:
case TraceLoggingDataType.Int8:
case TraceLoggingDataType.UInt8:
case TraceLoggingDataType.Int16:
diff --git a/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs b/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs
index b309695ff..27f57414f 100644
--- a/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs
+++ b/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_DIVIDEBYZERO;
}
- public DivideByZeroException(String message)
+ public DivideByZeroException(string message)
: base(message)
{
HResult = HResults.COR_E_DIVIDEBYZERO;
}
- public DivideByZeroException(String message, Exception innerException)
+ public DivideByZeroException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_DIVIDEBYZERO;
diff --git a/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs b/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs
index 14fb50d9c..bd29b8b13 100644
--- a/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_DLLNOTFOUND;
}
- public DllNotFoundException(String message)
+ public DllNotFoundException(string message)
: base(message)
{
HResult = HResults.COR_E_DLLNOTFOUND;
}
- public DllNotFoundException(String message, Exception inner)
+ public DllNotFoundException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_DLLNOTFOUND;
diff --git a/src/System.Private.CoreLib/shared/System/Double.cs b/src/System.Private.CoreLib/shared/System/Double.cs
index 146ee4600..d85b4bca9 100644
--- a/src/System.Private.CoreLib/shared/System/Double.cs
+++ b/src/System.Private.CoreLib/shared/System/Double.cs
@@ -24,9 +24,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Double : IComparable, IConvertible, IFormattable, IComparable<Double>, IEquatable<Double>, ISpanFormattable
+ public readonly struct Double : IComparable, IConvertible, IFormattable, IComparable<double>, IEquatable<double>, ISpanFormattable
{
- private double m_value; // Do not rename (binary serialization)
+ private readonly double m_value; // Do not rename (binary serialization)
//
// Public Constants
@@ -47,7 +47,7 @@ namespace System
/// <summary>Determines whether the specified value is finite (zero, subnormal, or normal).</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsFinite(double d)
+ public static unsafe bool IsFinite(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000;
@@ -56,7 +56,7 @@ namespace System
/// <summary>Determines whether the specified value is infinite.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsInfinity(double d)
+ public static unsafe bool IsInfinity(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) == 0x7FF0000000000000;
@@ -65,7 +65,7 @@ namespace System
/// <summary>Determines whether the specified value is NaN.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNaN(double d)
+ public static unsafe bool IsNaN(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000;
@@ -74,10 +74,9 @@ namespace System
/// <summary>Determines whether the specified value is negative.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNegative(double d)
+ public static unsafe bool IsNegative(double d)
{
- var bits = unchecked((ulong)BitConverter.DoubleToInt64Bits(d));
- return (bits & 0x8000000000000000) == 0x8000000000000000;
+ return BitConverter.DoubleToInt64Bits(d) < 0;
}
/// <summary>Determines whether the specified value is negative infinity.</summary>
@@ -91,7 +90,7 @@ namespace System
/// <summary>Determines whether the specified value is normal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsNormal(double d)
+ public static unsafe bool IsNormal(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
bits &= 0x7FFFFFFFFFFFFFFF;
@@ -109,7 +108,7 @@ namespace System
/// <summary>Determines whether the specified value is subnormal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsSubnormal(double d)
+ public static unsafe bool IsSubnormal(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
bits &= 0x7FFFFFFFFFFFFFFF;
@@ -123,13 +122,13 @@ namespace System
//
// Returns a value less than zero if this object
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Double)
+ if (value is double)
{
double d = (double)value;
if (m_value < d) return -1;
@@ -145,7 +144,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeDouble);
}
- public int CompareTo(Double value)
+ public int CompareTo(double value)
{
if (m_value < value) return -1;
if (m_value > value) return 1;
@@ -160,13 +159,13 @@ namespace System
// True if obj is another Double with the same value as the current instance. This is
// a method of object equality, that only returns true if obj is also a double.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Double))
+ if (!(obj is double))
{
return false;
}
- double temp = ((Double)obj).m_value;
+ double temp = ((double)obj).m_value;
// This code below is written this way for performance reasons i.e the != and == check is intentional.
if (temp == m_value)
{
@@ -176,42 +175,42 @@ namespace System
}
[NonVersionable]
- public static bool operator ==(Double left, Double right)
+ public static bool operator ==(double left, double right)
{
return left == right;
}
[NonVersionable]
- public static bool operator !=(Double left, Double right)
+ public static bool operator !=(double left, double right)
{
return left != right;
}
[NonVersionable]
- public static bool operator <(Double left, Double right)
+ public static bool operator <(double left, double right)
{
return left < right;
}
[NonVersionable]
- public static bool operator >(Double left, Double right)
+ public static bool operator >(double left, double right)
{
return left > right;
}
[NonVersionable]
- public static bool operator <=(Double left, Double right)
+ public static bool operator <=(double left, double right)
{
return left <= right;
}
[NonVersionable]
- public static bool operator >=(Double left, Double right)
+ public static bool operator >=(double left, double right)
{
return left >= right;
}
- public bool Equals(Double obj)
+ public bool Equals(double obj)
{
if (obj == m_value)
{
@@ -226,7 +225,7 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)] // 64-bit constants make the IL unusually large that makes the inliner to reject the method
public override int GetHashCode()
{
- var bits = Unsafe.As<double, long>(ref m_value);
+ var bits = Unsafe.As<double, long>(ref Unsafe.AsRef(in m_value));
// Optimized check for IsNan() || IsZero()
if (((bits - 1) & 0x7FFFFFFFFFFFFFFF) >= 0x7FF0000000000000)
@@ -238,22 +237,22 @@ namespace System
return unchecked((int)bits) ^ ((int)(bits >> 32));
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
}
@@ -263,26 +262,26 @@ namespace System
return Number.TryFormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten);
}
- public static double Parse(String s)
+ public static double Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDouble(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}
- public static double Parse(String s, NumberStyles style)
+ public static double Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDouble(s, style, NumberFormatInfo.CurrentInfo);
}
- public static double Parse(String s, IFormatProvider provider)
+ public static double Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDouble(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}
- public static double Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static double Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -297,7 +296,7 @@ namespace System
// PositiveInfinity or NegativeInfinity for a number that is too
// large or too small.
- public static double Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ public static double Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Float | NumberStyles.AllowThousands, IFormatProvider provider = null)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Number.ParseDouble(s, style, NumberFormatInfo.GetInstance(provider));
@@ -305,7 +304,7 @@ namespace System
- public static bool TryParse(String s, out double result)
+ public static bool TryParse(string s, out double result)
{
if (s == null)
{
@@ -321,7 +320,7 @@ namespace System
return TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
}
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out double result)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
@@ -346,15 +345,15 @@ namespace System
if (!success)
{
ReadOnlySpan<char> sTrim = s.Trim();
- if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
result = PositiveInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ else if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
result = NegativeInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ else if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
result = NaN;
}
@@ -435,7 +434,7 @@ namespace System
return m_value;
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -445,7 +444,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Double", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs b/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs
index 77303846a..f48e4be17 100644
--- a/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs
+++ b/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs
@@ -21,9 +21,9 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class DuplicateWaitObjectException : ArgumentException
{
- private static volatile String s_duplicateWaitObjectMessage = null;
+ private static volatile string s_duplicateWaitObjectMessage = null;
- private static String DuplicateWaitObjectMessage
+ private static string DuplicateWaitObjectMessage
{
get
{
@@ -41,19 +41,19 @@ namespace System
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
- public DuplicateWaitObjectException(String parameterName)
+ public DuplicateWaitObjectException(string parameterName)
: base(DuplicateWaitObjectMessage, parameterName)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
- public DuplicateWaitObjectException(String parameterName, String message)
+ public DuplicateWaitObjectException(string parameterName, string message)
: base(message, parameterName)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
- public DuplicateWaitObjectException(String message, Exception innerException)
+ public DuplicateWaitObjectException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
diff --git a/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs b/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs
index dac1cdb97..606743aa1 100644
--- a/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
- public EntryPointNotFoundException(String message)
+ public EntryPointNotFoundException(string message)
: base(message)
{
HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
- public EntryPointNotFoundException(String message, Exception inner)
+ public EntryPointNotFoundException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
diff --git a/src/System.Private.CoreLib/shared/System/EventHandler.cs b/src/System.Private.CoreLib/shared/System/EventHandler.cs
index 3d1cbfef2..c38e17ce6 100644
--- a/src/System.Private.CoreLib/shared/System/EventHandler.cs
+++ b/src/System.Private.CoreLib/shared/System/EventHandler.cs
@@ -6,7 +6,7 @@ using System;
namespace System
{
- public delegate void EventHandler(Object sender, EventArgs e);
+ public delegate void EventHandler(object sender, EventArgs e);
- public delegate void EventHandler<TEventArgs>(Object sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4
+ public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4
}
diff --git a/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs b/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs
index 5edd5cf19..5649cc082 100644
--- a/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs
+++ b/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs
@@ -31,13 +31,13 @@ namespace System
HResult = HResults.COR_E_EXECUTIONENGINE;
}
- public ExecutionEngineException(String message)
+ public ExecutionEngineException(string message)
: base(message)
{
HResult = HResults.COR_E_EXECUTIONENGINE;
}
- public ExecutionEngineException(String message, Exception innerException)
+ public ExecutionEngineException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_EXECUTIONENGINE;
diff --git a/src/System.Private.CoreLib/shared/System/FieldAccessException.cs b/src/System.Private.CoreLib/shared/System/FieldAccessException.cs
index cb28264d6..b23984133 100644
--- a/src/System.Private.CoreLib/shared/System/FieldAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/FieldAccessException.cs
@@ -23,13 +23,13 @@ namespace System
HResult = HResults.COR_E_FIELDACCESS;
}
- public FieldAccessException(String message)
+ public FieldAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_FIELDACCESS;
}
- public FieldAccessException(String message, Exception inner)
+ public FieldAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_FIELDACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/FormatException.cs b/src/System.Private.CoreLib/shared/System/FormatException.cs
index b0e273369..97d5001f3 100644
--- a/src/System.Private.CoreLib/shared/System/FormatException.cs
+++ b/src/System.Private.CoreLib/shared/System/FormatException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_FORMAT;
}
- public FormatException(String message)
+ public FormatException(string message)
: base(message)
{
HResult = HResults.COR_E_FORMAT;
}
- public FormatException(String message, Exception innerException)
+ public FormatException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_FORMAT;
diff --git a/src/System.Private.CoreLib/shared/System/FormattableString.cs b/src/System.Private.CoreLib/shared/System/FormattableString.cs
index 6369363b5..51863d6e7 100644
--- a/src/System.Private.CoreLib/shared/System/FormattableString.cs
+++ b/src/System.Private.CoreLib/shared/System/FormattableString.cs
@@ -73,6 +73,29 @@ namespace System
return formattable.ToString(Globalization.CultureInfo.InvariantCulture);
}
+ /// <summary>
+ /// Format the given object in the current culture. This static method may be
+ /// imported in C# by
+ /// <code>
+ /// using static System.FormattableString;
+ /// </code>.
+ /// Within the scope
+ /// of that import directive an interpolated string may be formatted in the
+ /// current culture by writing, for example,
+ /// <code>
+ /// CurrentCulture($"{{ lat = {latitude}; lon = {longitude} }}")
+ /// </code>
+ /// </summary>
+ public static string CurrentCulture(FormattableString formattable)
+ {
+ if (formattable == null)
+ {
+ throw new ArgumentNullException(nameof(formattable));
+ }
+
+ return formattable.ToString(Globalization.CultureInfo.CurrentCulture);
+ }
+
public override string ToString()
{
return ToString(Globalization.CultureInfo.CurrentCulture);
diff --git a/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs
new file mode 100644
index 000000000..225268122
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs
@@ -0,0 +1,76 @@
+// 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.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ /// <summary>
+ /// Schedules a callback roughly every gen 2 GC (you may see a Gen 0 an Gen 1 but only once)
+ /// (We can fix this by capturing the Gen 2 count at startup and testing, but I mostly don't care)
+ /// </summary>
+ internal sealed class Gen2GcCallback : CriticalFinalizerObject
+ {
+ private Gen2GcCallback()
+ : base()
+ {
+ }
+
+ /// <summary>
+ /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
+ /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
+ ///
+ /// NOTE: This callback will be kept alive until either the callback function returns false,
+ /// or the target object dies.
+ /// </summary>
+ public static void Register(Func<object, bool> callback, object targetObj)
+ {
+ // Create a unreachable object that remembers the callback function and target object.
+ Gen2GcCallback gcCallback = new Gen2GcCallback();
+ gcCallback.Setup(callback, targetObj);
+ }
+
+ private Func<object, bool> _callback;
+ private GCHandle _weakTargetObj;
+
+ private void Setup(Func<object, bool> callback, object targetObj)
+ {
+ _callback = callback;
+ _weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak);
+ }
+
+ ~Gen2GcCallback()
+ {
+ // Check to see if the target object is still alive.
+ object targetObj = _weakTargetObj.Target;
+ if (targetObj == null)
+ {
+ // The target object is dead, so this callback object is no longer needed.
+ _weakTargetObj.Free();
+ return;
+ }
+
+ // Execute the callback method.
+ try
+ {
+ if (!_callback(targetObj))
+ {
+ // If the callback returns false, this callback object is no longer needed.
+ return;
+ }
+ }
+ catch
+ {
+ // Ensure that we still get a chance to resurrect this object, even if the callback throws an exception.
+ }
+
+ // Resurrect ourselves by re-registering for finalization.
+ if (!Environment.HasShutdownStarted)
+ {
+ GC.ReRegisterForFinalize(this);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
index 49ad597ce..66a63694a 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
@@ -206,7 +206,7 @@ namespace System.Globalization
if (ticks < minValue.Ticks || ticks > maxValue.Ticks)
{
throw new ArgumentException(
- String.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange,
+ string.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange,
minValue, maxValue)));
}
}
@@ -736,7 +736,7 @@ namespace System.Globalization
public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
- internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
+ internal virtual bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
{
result = DateTime.MinValue;
try
@@ -818,7 +818,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(millisecond),
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1)));
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
index 17d6ed7a0..c94ac0ae5 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
@@ -32,7 +32,7 @@ namespace System.Globalization
internal partial class CalendarData
{
- private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId)
+ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
{
bool result = true;
result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.NativeName, out this.sNativeName);
@@ -134,16 +134,107 @@ namespace System.Globalization
{
List<string> datePatternsList = callbackContext.Results;
- datePatterns = new string[datePatternsList.Count];
for (int i = 0; i < datePatternsList.Count; i++)
{
- datePatterns[i] = NormalizeDatePattern(datePatternsList[i]);
+ datePatternsList[i] = NormalizeDatePattern(datePatternsList[i]);
}
+
+ if (dataType == CalendarDataType.ShortDates)
+ FixDefaultShortDatePattern(datePatternsList);
+
+ datePatterns = datePatternsList.ToArray();
}
return result;
}
+ // FixDefaultShortDatePattern will convert the default short date pattern from using 'yy' to using 'yyyy'
+ // And will ensure the original pattern still exist in the list.
+ // doing that will have the short date pattern format the year as 4-digit number and not just 2-digit number.
+ // Example: June 5, 2018 will be formatted to something like 6/5/2018 instead of 6/5/18 fro en-US culture.
+ private static void FixDefaultShortDatePattern(List<string> shortDatePatterns)
+ {
+ if (shortDatePatterns.Count == 0)
+ return;
+
+ string s = shortDatePatterns[0];
+
+ // We are not expecting any pattern have length more than 100.
+ // We have to do this check to prevent stack overflow as we allocate the buffer on the stack.
+ if (s.Length > 100)
+ return;
+
+ Span<char> modifiedPattern = stackalloc char[s.Length + 2];
+ int index = 0;
+
+ while (index < s.Length)
+ {
+ if (s[index] == '\'')
+ {
+ do
+ {
+ modifiedPattern[index] = s[index];
+ index++;
+ } while (index < s.Length && s[index] != '\'');
+
+ if (index >= s.Length)
+ return;
+ }
+ else if (s[index] == 'y')
+ {
+ modifiedPattern[index] = 'y';
+ break;
+ }
+
+ modifiedPattern[index] = s[index];
+ index++;
+ }
+
+ if (index >= s.Length - 1 || s[index + 1] != 'y')
+ {
+ // not a 'yy' pattern
+ return;
+ }
+
+ if (index + 2 < s.Length && s[index + 2] == 'y')
+ {
+ // we have 'yyy' then nothing to do
+ return;
+ }
+
+ // we are sure now we have 'yy' pattern
+
+ Debug.Assert(index + 3 < modifiedPattern.Length);
+
+ modifiedPattern[index + 1] = 'y'; // second y
+ modifiedPattern[index + 2] = 'y'; // third y
+ modifiedPattern[index + 3] = 'y'; // fourth y
+
+ index += 2;
+
+ // Now, copy the rest of the pattern to the destination buffer
+ while (index < s.Length)
+ {
+ modifiedPattern[index + 2] = s[index];
+ index++;
+ }
+
+ shortDatePatterns[0] = modifiedPattern.ToString();
+
+ for (int i = 1; i < shortDatePatterns.Count; i++)
+ {
+ if (shortDatePatterns[i] == shortDatePatterns[0])
+ {
+ // Found match in the list to the new constructed pattern, then replace it with the original modified pattern
+ shortDatePatterns[i] = s;
+ return;
+ }
+ }
+
+ // if we come here means the newly constructed pattern not found on the list, then add the original pattern
+ shortDatePatterns.Add(s);
+ }
+
/// <summary>
/// The ICU date format characters are not exactly the same as the .NET date format characters.
/// NormalizeDatePattern will take in an ICU date pattern and return the equivalent .NET date pattern.
@@ -220,7 +311,7 @@ namespace System.Globalization
break;
default:
const string unsupportedDateFieldSymbols = "YuUrQqwWDFg";
- Debug.Assert(unsupportedDateFieldSymbols.IndexOf(input[index]) == -1,
+ Debug.Assert(!unsupportedDateFieldSymbols.Contains(input[index]),
string.Format(CultureInfo.InvariantCulture,
"Encountered an unexpected date field symbol '{0}' from ICU which has no known corresponding .NET equivalent.",
input[index]));
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
index 03f9088d6..de5037441 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
@@ -13,7 +13,7 @@ namespace System.Globalization
{
internal partial class CalendarData
{
- private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId)
+ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -127,7 +127,7 @@ namespace System.Globalization
}
// Call native side to figure out which calendars are allowed
- internal static int GetCalendars(String localeName, bool useUserOverride, CalendarId[] calendars)
+ internal static int GetCalendars(string localeName, bool useUserOverride, CalendarId[] calendars)
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -451,7 +451,7 @@ namespace System.Globalization
}
}
- private static unsafe String GetUserDefaultLocaleName()
+ private static unsafe string GetUserDefaultLocaleName()
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -463,7 +463,7 @@ namespace System.Globalization
char* localeName = stackalloc char[LOCALE_NAME_MAX_LENGTH];
result = CultureData.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, localeName, LOCALE_NAME_MAX_LENGTH);
- return result <= 0 ? "" : new String(localeName, 0, result - 1); // exclude the null termination
+ return result <= 0 ? "" : new string(localeName, 0, result - 1); // exclude the null termination
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
index ea70a1ce9..56ddf7579 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
@@ -19,26 +19,26 @@ namespace System.Globalization
internal const int MAX_CALENDARS = 23;
// Identity
- internal String sNativeName; // Calendar Name for the locale
+ internal string sNativeName; // Calendar Name for the locale
// Formats
- internal String[] saShortDates; // Short Data format, default first
- internal String[] saYearMonths; // Year/Month Data format, default first
- internal String[] saLongDates; // Long Data format, default first
- internal String sMonthDay; // Month/Day format
+ internal string[] saShortDates; // Short Data format, default first
+ internal string[] saYearMonths; // Year/Month Data format, default first
+ internal string[] saLongDates; // Long Data format, default first
+ internal string sMonthDay; // Month/Day format
// Calendar Parts Names
- internal String[] saEraNames; // Names of Eras
- internal String[] saAbbrevEraNames; // Abbreviated Era Names
- internal String[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English
- internal String[] saDayNames; // Day Names, null to use locale data, starts on Sunday
- internal String[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
- internal String[] saSuperShortDayNames; // Super short Day of week names
- internal String[] saMonthNames; // Month Names (13)
- internal String[] saAbbrevMonthNames; // Abbrev Month Names (13)
- internal String[] saMonthGenitiveNames; // Genitive Month Names (13)
- internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
- internal String[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year.
+ internal string[] saEraNames; // Names of Eras
+ internal string[] saAbbrevEraNames; // Abbreviated Era Names
+ internal string[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English
+ internal string[] saDayNames; // Day Names, null to use locale data, starts on Sunday
+ internal string[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
+ internal string[] saSuperShortDayNames; // Super short Day of week names
+ internal string[] saMonthNames; // Month Names (13)
+ internal string[] saAbbrevMonthNames; // Abbrev Month Names (13)
+ internal string[] saMonthGenitiveNames; // Genitive Month Names (13)
+ internal string[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
+ internal string[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year.
// Integers at end to make marshaller happier
internal int iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
@@ -69,22 +69,22 @@ namespace System.Globalization
invariant.iCurrentEra = 1; // Current era #
// Formats
- invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
- invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy" }; // long date format
- invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format
+ invariant.saShortDates = new string[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
+ invariant.saLongDates = new string[] { "dddd, dd MMMM yyyy" }; // long date format
+ invariant.saYearMonths = new string[] { "yyyy MMMM" }; // year month format
invariant.sMonthDay = "MMMM dd"; // Month day pattern
// Calendar Parts Names
- invariant.saEraNames = new String[] { "A.D." }; // Era names
- invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names
- invariant.saAbbrevEnglishEraNames = new String[] { "AD" }; // Abbreviated era names in English
- invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names
- invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
- invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
- invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December", String.Empty}; // month names
- invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", String.Empty}; // abbreviated month names
+ invariant.saEraNames = new string[] { "A.D." }; // Era names
+ invariant.saAbbrevEraNames = new string[] { "AD" }; // Abbreviated Era names
+ invariant.saAbbrevEnglishEraNames = new string[] { "AD" }; // Abbreviated era names in English
+ invariant.saDayNames = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names
+ invariant.saAbbrevDayNames = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
+ invariant.saSuperShortDayNames = new string[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
+ invariant.saMonthNames = new string[] { "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December", string.Empty}; // month names
+ invariant.saAbbrevMonthNames = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", string.Empty}; // abbreviated month names
invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant)
invariant.saAbbrevMonthGenitiveNames = invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant)
@@ -97,7 +97,7 @@ namespace System.Globalization
//
// Get a bunch of data for a calendar
//
- internal CalendarData(String localeName, CalendarId calendarId, bool bUseUserOverrides)
+ internal CalendarData(string localeName, CalendarId calendarId, bool bUseUserOverrides)
{
this.bUseUserOverrides = bUseUserOverrides;
@@ -109,7 +109,7 @@ namespace System.Globalization
// Something failed, try invariant for missing parts
// This is really not good, but we don't want the callers to crash.
- if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale.
+ if (this.sNativeName == null) this.sNativeName = string.Empty; // Calendar Name for the locale.
// Formats
if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first
@@ -138,16 +138,16 @@ namespace System.Globalization
}
else
{
- this.sNativeName = String.Empty;
+ this.sNativeName = string.Empty;
}
}
// Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc)
- if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
+ if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || string.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant)
- if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
+ if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
- if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || String.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
+ if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || string.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
this.saLeapYearMonthNames = this.saMonthNames;
InitializeEraNames(localeName, calendarId);
@@ -162,7 +162,7 @@ namespace System.Globalization
else
{
// For all others just use the an empty string (doesn't matter we'll never ask for it for other calendars)
- this.saAbbrevEnglishEraNames = new String[] { "" };
+ this.saAbbrevEnglishEraNames = new string[] { "" };
}
// Japanese is the only thing with > 1 era. Its current era # is how many ever
@@ -178,60 +178,60 @@ namespace System.Globalization
// For Localized Gregorian we really expect the data from the OS.
case CalendarId.GREGORIAN:
// Fallback for CoreCLR < Win7 or culture.dll missing
- if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || string.IsNullOrEmpty(this.saEraNames[0]))
{
- this.saEraNames = new String[] { "A.D." };
+ this.saEraNames = new string[] { "A.D." };
}
break;
// The rest of the calendars have constant data, so we'll just use that
case CalendarId.GREGORIAN_US:
case CalendarId.JULIAN:
- this.saEraNames = new String[] { "A.D." };
+ this.saEraNames = new string[] { "A.D." };
break;
case CalendarId.HEBREW:
- this.saEraNames = new String[] { "C.E." };
+ this.saEraNames = new string[] { "C.E." };
break;
case CalendarId.HIJRI:
case CalendarId.UMALQURA:
if (localeName == "dv-MV")
{
// Special case for Divehi
- this.saEraNames = new String[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
+ this.saEraNames = new string[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
}
else
{
- this.saEraNames = new String[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
+ this.saEraNames = new string[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
}
break;
case CalendarId.GREGORIAN_ARABIC:
case CalendarId.GREGORIAN_XLIT_ENGLISH:
case CalendarId.GREGORIAN_XLIT_FRENCH:
// These are all the same:
- this.saEraNames = new String[] { "\x0645" };
+ this.saEraNames = new string[] { "\x0645" };
break;
case CalendarId.GREGORIAN_ME_FRENCH:
- this.saEraNames = new String[] { "ap. J.-C." };
+ this.saEraNames = new string[] { "ap. J.-C." };
break;
case CalendarId.TAIWAN:
if (SystemSupportsTaiwaneseCalendar())
{
- this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" };
+ this.saEraNames = new string[] { "\x4e2d\x83ef\x6c11\x570b" };
}
else
{
- this.saEraNames = new String[] { String.Empty };
+ this.saEraNames = new string[] { string.Empty };
}
break;
case CalendarId.KOREA:
- this.saEraNames = new String[] { "\xb2e8\xae30" };
+ this.saEraNames = new string[] { "\xb2e8\xae30" };
break;
case CalendarId.THAI:
- this.saEraNames = new String[] { "\x0e1e\x002e\x0e28\x002e" };
+ this.saEraNames = new string[] { "\x0e1e\x002e\x0e28\x002e" };
break;
case CalendarId.JAPAN:
@@ -240,9 +240,9 @@ namespace System.Globalization
break;
case CalendarId.PERSIAN:
- if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || string.IsNullOrEmpty(this.saEraNames[0]))
{
- this.saEraNames = new String[] { "\x0647\x002e\x0634" };
+ this.saEraNames = new string[] { "\x0647\x002e\x0634" };
}
break;
@@ -261,16 +261,16 @@ namespace System.Globalization
// For Localized Gregorian we really expect the data from the OS.
case CalendarId.GREGORIAN:
// Fallback for CoreCLR < Win7 or culture.dll missing
- if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevEraNames[0]))
{
- this.saAbbrevEraNames = new String[] { "AD" };
+ this.saAbbrevEraNames = new string[] { "AD" };
}
break;
// The rest of the calendars have constant data, so we'll just use that
case CalendarId.GREGORIAN_US:
case CalendarId.JULIAN:
- this.saAbbrevEraNames = new String[] { "AD" };
+ this.saAbbrevEraNames = new string[] { "AD" };
break;
case CalendarId.JAPAN:
case CalendarId.JAPANESELUNISOLAR:
@@ -281,16 +281,16 @@ namespace System.Globalization
if (localeName == "dv-MV")
{
// Special case for Divehi
- this.saAbbrevEraNames = new String[] { "\x0780\x002e" };
+ this.saAbbrevEraNames = new string[] { "\x0780\x002e" };
}
else
{
- this.saAbbrevEraNames = new String[] { "\x0647\x0640" };
+ this.saAbbrevEraNames = new string[] { "\x0647\x0640" };
}
break;
case CalendarId.TAIWAN:
// Get era name and abbreviate it
- this.saAbbrevEraNames = new String[1];
+ this.saAbbrevEraNames = new string[1];
if (this.saEraNames[0].Length == 4)
{
this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2, 2);
@@ -302,7 +302,7 @@ namespace System.Globalization
break;
case CalendarId.PERSIAN:
- if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevEraNames[0]))
{
this.saAbbrevEraNames = this.saEraNames;
}
@@ -326,13 +326,13 @@ namespace System.Globalization
// Get a culture name
// TODO: Note that this doesn't handle the new calendars (lunisolar, etc)
- String culture = CalendarIdToCultureName(calendarId);
+ string culture = CalendarIdToCultureName(calendarId);
// Return our calendar
return CultureInfo.GetCultureInfo(culture)._cultureData.GetCalendar(calendarId);
}
- private static String CalendarIdToCultureName(CalendarId calendarId)
+ private static string CalendarIdToCultureName(CalendarId calendarId)
{
switch (calendarId)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
index 0cd8429bb..d8d621cb0 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
@@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////////////
using System.Diagnostics;
+using System.Text;
namespace System.Globalization
{
@@ -29,6 +30,7 @@ namespace System.Globalization
internal const char HIGH_SURROGATE_END = '\udbff';
internal const char LOW_SURROGATE_START = '\udc00';
internal const char LOW_SURROGATE_END = '\udfff';
+ internal const int HIGH_SURROGATE_RANGE = 0x3FF;
internal const int UNICODE_CATEGORY_OFFSET = 0;
internal const int BIDI_CATEGORY_OFFSET = 1;
@@ -41,7 +43,7 @@ namespace System.Globalization
//
// Actions:
// Convert the BMP character or surrogate pointed by index to a UTF32 value.
- // This is similar to Char.ConvertToUTF32, but the difference is that
+ // This is similar to char.ConvertToUTF32, but the difference is that
// it does not throw exceptions when invalid surrogate characters are passed in.
//
// WARNING: since it doesn't throw an exception it CAN return a value
@@ -49,17 +51,17 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static int InternalConvertToUtf32(String s, int index)
+ internal static int InternalConvertToUtf32(string s, int index)
{
Debug.Assert(s != null, "s != null");
Debug.Assert(index >= 0 && index < s.Length, "index < s.Length");
if (index < s.Length - 1)
{
int temp1 = (int)s[index] - HIGH_SURROGATE_START;
- if (temp1 >= 0 && temp1 <= 0x3ff)
+ if (temp1 >= 0 && temp1 <= HIGH_SURROGATE_RANGE)
{
int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if (temp2 >= 0 && temp2 <= 0x3ff)
+ if (temp2 >= 0 && temp2 <= HIGH_SURROGATE_RANGE)
{
// Convert the surrogate to UTF32 and get the result.
return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
@@ -68,6 +70,29 @@ namespace System.Globalization
}
return ((int)s[index]);
}
+
+ internal static int InternalConvertToUtf32(StringBuilder s, int index)
+ {
+ Debug.Assert(s != null, "s != null");
+ Debug.Assert(index >= 0 && index < s.Length, "index < s.Length");
+
+ int c = (int)s[index];
+ if (index < s.Length - 1)
+ {
+ int temp1 = c - HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= HIGH_SURROGATE_RANGE)
+ {
+ int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= HIGH_SURROGATE_RANGE)
+ {
+ // Convert the surrogate to UTF32 and get the result.
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ }
+ }
+ }
+ return c;
+ }
+
////////////////////////////////////////////////////////////////////////
//
// Convert a character or a surrogate pair starting at index of string s
@@ -90,7 +115,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static int InternalConvertToUtf32(String s, int index, out int charLength)
+ internal static int InternalConvertToUtf32(string s, int index, out int charLength)
{
Debug.Assert(s != null, "s != null");
Debug.Assert(s.Length > 0, "s.Length > 0");
@@ -99,10 +124,10 @@ namespace System.Globalization
if (index < s.Length - 1)
{
int temp1 = (int)s[index] - HIGH_SURROGATE_START;
- if (temp1 >= 0 && temp1 <= 0x3ff)
+ if (temp1 >= 0 && temp1 <= HIGH_SURROGATE_RANGE)
{
int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if (temp2 >= 0 && temp2 <= 0x3ff)
+ if (temp2 >= 0 && temp2 <= HIGH_SURROGATE_RANGE)
{
// Convert the surrogate to UTF32 and get the result.
charLength++;
@@ -121,7 +146,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static bool IsWhiteSpace(String s, int index)
+ internal static bool IsWhiteSpace(string s, int index)
{
Debug.Assert(s != null, "s!=null");
Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
@@ -221,7 +246,7 @@ namespace System.Globalization
}
- public static double GetNumericValue(String s, int index)
+ public static double GetNumericValue(string s, int index)
{
if (s == null)
{
@@ -239,7 +264,7 @@ namespace System.Globalization
return (sbyte)(InternalGetDigitValues(ch) >> 8);
}
- public static int GetDecimalDigitValue(String s, int index)
+ public static int GetDecimalDigitValue(string s, int index)
{
if (s == null)
{
@@ -259,7 +284,7 @@ namespace System.Globalization
return (sbyte)(InternalGetDigitValues(ch) & 0x00FF);
}
- public static int GetDigitValue(String s, int index)
+ public static int GetDigitValue(string s, int index)
{
if (s == null)
{
@@ -279,7 +304,7 @@ namespace System.Globalization
return (GetUnicodeCategory((int)ch));
}
- public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ public static UnicodeCategory GetUnicodeCategory(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -347,7 +372,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index)
+ internal static UnicodeCategory InternalGetUnicodeCategory(string value, int index)
{
Debug.Assert(value != null, "value can not be null");
Debug.Assert(index < value.Length, "index < value.Length");
@@ -355,7 +380,7 @@ namespace System.Globalization
return (GetUnicodeCategory(InternalConvertToUtf32(value, index)));
}
- internal static BidiCategory GetBidiCategory(String s, int index)
+ internal static BidiCategory GetBidiCategory(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -368,6 +393,14 @@ namespace System.Globalization
return ((BidiCategory) InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET));
}
+ internal static BidiCategory GetBidiCategory(StringBuilder s, int index)
+ {
+ Debug.Assert(s != null, "s can not be null");
+ Debug.Assert(index >= 0 && index < s.Length, "invalid index"); ;
+
+ return ((BidiCategory) InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET));
+ }
+
////////////////////////////////////////////////////////////////////////
//
// Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
@@ -375,7 +408,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength)
+ internal static UnicodeCategory InternalGetUnicodeCategory(string str, int index, out int charLength)
{
Debug.Assert(str != null, "str can not be null");
Debug.Assert(str.Length > 0, "str.Length > 0"); ;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
index d2b52b97b..39448e183 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
@@ -8,9 +8,9 @@ namespace System.Globalization
/*
** Calendar support range:
** Calendar Minimum Maximum
- ** ========== ========== ==========
+ ** ========== ========== ==========
** Gregorian 1901/02/19 2101/01/28
- ** ChineseLunisolar 1901/01/01 2100/12/29
+ ** ChineseLunisolar 1901/01/01 2100/12/29
*/
public class ChineseLunisolarCalendar : EastAsianLunisolarCalendar
@@ -43,7 +43,6 @@ namespace System.Globalization
}
}
-
public override DateTime MaxSupportedDateTime
{
get
@@ -56,218 +55,222 @@ namespace System.Globalization
{
get
{
- // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations
+ // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations [1]
+ // [1] Reingold, Edward M, and Nachum Dershowitz. Calendrical Tabulations, 1900 - 2200.Cambridge: Cambridge Univ. Press, 2002.Print.
return 384;
}
}
-
+ // Data for years 1901-1905 and 1907-2100 matches output of Calendrical Calculations [2] and published calendar tables [3].
+ // For 1906, month 4 of the Chinese year starts on 24 Apr 1906 and has 29 days. This is historially accurate
+ // but different to the values in [1] and output from [2]. This is due to a change in the astronomical methods used
+ // by the Chinese to calculate the calendar from 1913 onwards (see warnings in [1]).
+ // [2] Reingold, Edward M, and Nachum Dershowitz. Calendrical Calculations: The Ultimate Edition. Cambridge [etc.: Cambridge University Press, 2018. Print.
+ // [3] Wang, Jianmin. Xin Bian Wan Nian Li: (1840-2050) Chong Bian Ben. Beijing: Ke xue pu ji chu ban she, 1990. Print.
private static readonly int[,] s_yinfo =
{
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 1901 */
- { 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
-1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
-1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
-1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
-1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
-2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
-2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-2051 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-2052 */{ 8 , 2 , 1 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-2053 */{ 0 , 2 , 19 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-2054 */{ 0 , 2 , 8 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-2055 */{ 6 , 1 , 28 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-2056 */{ 0 , 2 , 15 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-2057 */{ 0 , 2 , 4 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
-2058 */{ 4 , 1 , 24 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-2059 */{ 0 , 2 , 12 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
-2060 */{ 0 , 2 , 2 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2061 */{ 3 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-2062 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2063 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2064 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2065 */{ 0 , 2 , 5 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2066 */{ 5 , 1 , 26 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2067 */{ 0 , 2 , 14 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-2068 */{ 0 , 2 , 3 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-2069 */{ 4 , 1 , 23 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-2070 */{ 0 , 2 , 11 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
-2071 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-2072 */{ 0 , 2 , 19 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2073 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2074 */{ 6 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2075 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2076 */{ 0 , 2 , 5 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
-2077 */{ 4 , 1 , 24 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-2078 */{ 0 , 2 , 12 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2079 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2080 */{ 3 , 1 , 22 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
-2081 */{ 0 , 2 , 9 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-2082 */{ 7 , 1 , 29 , 29336 },/* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
-2083 */{ 0 , 2 , 17 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2084 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2085 */{ 5 , 1 , 26 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2086 */{ 0 , 2 , 14 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2087 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-2088 */{ 4 , 1 , 24 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-2089 */{ 0 , 2 , 10 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-2090 */{ 8 , 1 , 30 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2091 */{ 0 , 2 , 18 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2092 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-2093 */{ 6 , 1 , 27 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2094 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-2095 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-2096 */{ 4 , 1 , 25 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-2097 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2098 */{ 0 , 2 , 1 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
-2099 */{ 2 , 1 , 21 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
-2100 */{ 0 , 2 , 9 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
- */};
-
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1901 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1902 */ { 00, 02, 08, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1903 */ { 05, 01, 29, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */ { 00, 02, 16, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1905 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1906 */ { 04, 01, 25, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1908 */ { 00, 02, 02, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1909 */ { 02, 01, 22, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */ { 00, 02, 10, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1911 */ { 06, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1913 */ { 00, 02, 06, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1914 */ { 05, 01, 26, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1915 */ { 00, 02, 14, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1916 */ { 00, 02, 03, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1917 */ { 02, 01, 23, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */ { 00, 02, 11, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1919 */ { 07, 02, 01, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1920 */ { 00, 02, 20, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1921 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1922 */ { 05, 01, 28, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */ { 00, 02, 16, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1924 */ { 00, 02, 05, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1925 */ { 04, 01, 24, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1926 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1927 */ { 00, 02, 02, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
+1928 */ { 02, 01, 23, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1929 */ { 00, 02, 10, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1930 */ { 06, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1932 */ { 00, 02, 06, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1933 */ { 05, 01, 26, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */ { 00, 02, 14, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1935 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1936 */ { 03, 01, 24, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1937 */ { 00, 02, 11, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1938 */ { 07, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */ { 00, 02, 19, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1940 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1941 */ { 06, 01, 27, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */ { 00, 02, 15, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1943 */ { 00, 02, 05, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1944 */ { 04, 01, 25, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1945 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1946 */ { 00, 02, 02, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1947 */ { 02, 01, 22, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1949 */ { 07, 01, 29, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1950 */ { 00, 02, 17, 0b0110110010100000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 354
+1951 */ { 00, 02, 06, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1952 */ { 05, 01, 27, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1953 */ { 00, 02, 14, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1954 */ { 00, 02, 03, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1955 */ { 03, 01, 24, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1957 */ { 08, 01, 31, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1958 */ { 00, 02, 18, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1959 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1965 */ { 00, 02, 02, 0b0101001001100000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 353
+1966 */ { 03, 01, 21, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1968 */ { 07, 01, 30, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1970 */ { 00, 02, 06, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */ { 00, 02, 15, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+1973 */ { 00, 02, 03, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1976 */ { 08, 01, 31, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1978 */ { 00, 02, 07, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1982 */ { 04, 01, 25, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1987 */ { 06, 01, 29, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
+1988 */ { 00, 02, 17, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1989 */ { 00, 02, 06, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
+1990 */ { 05, 01, 27, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1995 */ { 08, 01, 31, 0b0110101100101000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1996 */ { 00, 02, 19, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1997 */ { 00, 02, 07, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1998 */ { 05, 01, 28, 0b1001001101101000 }, /* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
+1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2001 */ { 04, 01, 24, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */ { 00, 02, 09, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2012 */ { 04, 01, 23, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2013 */ { 00, 02, 10, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
+2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2017 */ { 06, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2019 */ { 00, 02, 05, 0b1010100100110000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 354
+2020 */ { 04, 01, 25, 0b0111010010101000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2023 */ { 02, 01, 22, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */ { 00, 02, 17, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+2027 */ { 00, 02, 06, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+2028 */ { 05, 01, 26, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2029 */ { 00, 02, 13, 0b1101010100110000 }, /* 30 30 29 30 29 30 29 30 29 29 30 30 355
+2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+2031 */ { 03, 01, 23, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */ { 00, 02, 19, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+2036 */ { 06, 01, 28, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */ { 00, 02, 12, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+2041 */ { 00, 02, 01, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+2046 */ { 00, 02, 06, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */ { 00, 02, 14, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
+2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+2050 */ { 03, 01, 23, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+2051 */ { 00, 02, 11, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+2052 */ { 08, 02, 01, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+2053 */ { 00, 02, 19, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+2054 */ { 00, 02, 08, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+2055 */ { 06, 01, 28, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+2056 */ { 00, 02, 15, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+2057 */ { 00, 02, 04, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2058 */ { 04, 01, 24, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+2059 */ { 00, 02, 12, 0b1010101011100000 }, /* 30 29 30 29 30 29 30 29 30 30 30 29 355
+2060 */ { 00, 02, 02, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2061 */ { 03, 01, 21, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+2062 */ { 00, 02, 09, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2063 */ { 07, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2064 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2065 */ { 00, 02, 05, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2066 */ { 05, 01, 26, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2067 */ { 00, 02, 14, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+2068 */ { 00, 02, 03, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+2069 */ { 04, 01, 23, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+2070 */ { 00, 02, 11, 0b0101001011010000 }, /* 29 30 29 30 29 29 30 29 30 30 29 30 354
+2071 */ { 08, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+2072 */ { 00, 02, 19, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2073 */ { 00, 02, 07, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2074 */ { 06, 01, 27, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2075 */ { 00, 02, 15, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2076 */ { 00, 02, 05, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
+2077 */ { 04, 01, 24, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+2078 */ { 00, 02, 12, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2079 */ { 00, 02, 02, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2080 */ { 03, 01, 22, 0b1010100100111000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+2081 */ { 00, 02, 09, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+2082 */ { 07, 01, 29, 0b0111001010011000 }, /* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
+2083 */ { 00, 02, 17, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2084 */ { 00, 02, 06, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2085 */ { 05, 01, 26, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2086 */ { 00, 02, 14, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2087 */ { 00, 02, 03, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+2088 */ { 04, 01, 24, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+2089 */ { 00, 02, 10, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+2090 */ { 08, 01, 30, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2091 */ { 00, 02, 18, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2092 */ { 00, 02, 07, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+2093 */ { 06, 01, 27, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2094 */ { 00, 02, 15, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+2095 */ { 00, 02, 05, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+2096 */ { 04, 01, 25, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+2097 */ { 00, 02, 12, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+2098 */ { 00, 02, 01, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
+2099 */ { 02, 01, 21, 0b1101100100101000 }, /* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+2100 */ { 00, 02, 09, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+ */ };
internal override int MinCalendarYear
{
@@ -315,7 +318,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
}
@@ -339,7 +342,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
}
@@ -374,7 +377,6 @@ namespace System.Globalization
}
}
-
public override int[] Eras
{
get
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
index 29e4f5321..16201b8d1 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
@@ -18,7 +18,7 @@ namespace System.Globalization
fixed (char* pSource = source) fixed (char* pValue = value)
{
char* pSrc = &pSource[startIndex];
- int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, start : true);
+ int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, fromBeginning : true);
if (index >= 0)
{
return index + startIndex;
@@ -27,7 +27,7 @@ namespace System.Globalization
}
}
- internal static unsafe int InvariantIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ internal static unsafe int InvariantIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning = true)
{
Debug.Assert(source.Length != 0);
Debug.Assert(value.Length != 0);
@@ -35,7 +35,7 @@ namespace System.Globalization
fixed (char* pSource = &MemoryMarshal.GetReference(source))
fixed (char* pValue = &MemoryMarshal.GetReference(value))
{
- return InvariantFindString(pSource, source.Length, pValue, value.Length, ignoreCase, start: true);
+ return InvariantFindString(pSource, source.Length, pValue, value.Length, ignoreCase, fromBeginning);
}
}
@@ -48,7 +48,7 @@ namespace System.Globalization
fixed (char* pSource = source) fixed (char* pValue = value)
{
char* pSrc = &pSource[startIndex - count + 1];
- int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, start : false);
+ int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, fromBeginning : false);
if (index >= 0)
{
return index + startIndex - count + 1;
@@ -57,7 +57,7 @@ namespace System.Globalization
}
}
- private static unsafe int InvariantFindString(char* source, int sourceCount, char* value, int valueCount, bool ignoreCase, bool start)
+ private static unsafe int InvariantFindString(char* source, int sourceCount, char* value, int valueCount, bool ignoreCase, bool fromBeginning)
{
int ctrSource = 0; // index value into source
int ctrValue = 0; // index value into value
@@ -72,7 +72,7 @@ namespace System.Globalization
if (valueCount == 0)
{
- return start ? 0 : sourceCount - 1;
+ return fromBeginning ? 0 : sourceCount - 1;
}
if (sourceCount < valueCount)
@@ -80,7 +80,7 @@ namespace System.Globalization
return -1;
}
- if (start)
+ if (fromBeginning)
{
lastSourceStart = sourceCount - valueCount;
if (ignoreCase)
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
new file mode 100644
index 000000000..f51754009
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
@@ -0,0 +1,1074 @@
+// 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.Buffers;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Globalization
+{
+ public partial class CompareInfo
+ {
+ [NonSerialized]
+ private Interop.Globalization.SafeSortHandle _sortHandle;
+
+ [NonSerialized]
+ private bool _isAsciiEqualityOrdinal;
+
+ private void InitSort(CultureInfo culture)
+ {
+ _sortName = culture.SortName;
+
+ if (_invariantMode)
+ {
+ _isAsciiEqualityOrdinal = true;
+ }
+ else
+ {
+ Interop.Globalization.ResultCode resultCode = Interop.Globalization.GetSortHandle(GetNullTerminatedUtf8String(_sortName), out _sortHandle);
+ if (resultCode != Interop.Globalization.ResultCode.Success)
+ {
+ _sortHandle.Dispose();
+
+ if (resultCode == Interop.Globalization.ResultCode.OutOfMemory)
+ throw new OutOfMemoryException();
+
+ throw new ExternalException(SR.Arg_ExternalException);
+ }
+ _isAsciiEqualityOrdinal = (_sortName == "en-US" || _sortName == "");
+ }
+ }
+
+ internal static unsafe int IndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ Debug.Assert(source != null);
+ Debug.Assert(value != null);
+
+ if (value.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (count < value.Length)
+ {
+ return -1;
+ }
+
+ if (ignoreCase)
+ {
+ fixed (char* pSource = source)
+ {
+ int index = Interop.Globalization.IndexOfOrdinalIgnoreCase(value, value.Length, pSource + startIndex, count, findLast: false);
+ return index != -1 ?
+ startIndex + index :
+ -1;
+ }
+ }
+
+ int endIndex = startIndex + (count - value.Length);
+ for (int i = startIndex; i <= endIndex; i++)
+ {
+ int valueIndex, sourceIndex;
+
+ for (valueIndex = 0, sourceIndex = i;
+ valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
+ valueIndex++, sourceIndex++) ;
+
+ if (valueIndex == value.Length)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ internal static unsafe int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ Debug.Assert(source.Length != 0);
+ Debug.Assert(value.Length != 0);
+
+ if (source.Length < value.Length)
+ {
+ return -1;
+ }
+
+ if (ignoreCase)
+ {
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pValue = &MemoryMarshal.GetReference(value))
+ {
+ return Interop.Globalization.IndexOfOrdinalIgnoreCase(pValue, value.Length, pSource, source.Length, findLast: !fromBeginning);
+ }
+ }
+
+ int startIndex, endIndex, jump;
+ if (fromBeginning)
+ {
+ // Left to right, from zero to last possible index in the source string.
+ // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
+ startIndex = 0;
+ endIndex = source.Length - value.Length + 1;
+ jump = 1;
+ }
+ else
+ {
+ // Right to left, from first possible index in the source string to zero.
+ // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
+ startIndex = source.Length - value.Length;
+ endIndex = -1;
+ jump = -1;
+ }
+
+ for (int i = startIndex; i != endIndex; i += jump)
+ {
+ int valueIndex, sourceIndex;
+
+ for (valueIndex = 0, sourceIndex = i;
+ valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
+ valueIndex++, sourceIndex++)
+ ;
+
+ if (valueIndex == value.Length)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ internal static unsafe int LastIndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ Debug.Assert(source != null);
+ Debug.Assert(value != null);
+
+ if (value.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (count < value.Length)
+ {
+ return -1;
+ }
+
+ // startIndex is the index into source where we start search backwards from.
+ // leftStartIndex is the index into source of the start of the string that is
+ // count characters away from startIndex.
+ int leftStartIndex = startIndex - count + 1;
+
+ if (ignoreCase)
+ {
+ fixed (char* pSource = source)
+ {
+ int lastIndex = Interop.Globalization.IndexOfOrdinalIgnoreCase(value, value.Length, pSource + leftStartIndex, count, findLast: true);
+ return lastIndex != -1 ?
+ leftStartIndex + lastIndex :
+ -1;
+ }
+ }
+
+ for (int i = startIndex - value.Length + 1; i >= leftStartIndex; i--)
+ {
+ int valueIndex, sourceIndex;
+
+ for (valueIndex = 0, sourceIndex = i;
+ valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
+ valueIndex++, sourceIndex++) ;
+
+ if (valueIndex == value.Length) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ private static unsafe int CompareStringOrdinalIgnoreCase(ref char string1, int count1, ref char string2, int count2)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ fixed (char* char1 = &string1)
+ fixed (char* char2 = &string2)
+ {
+ return Interop.Globalization.CompareStringOrdinalIgnoreCase(char1, count1, char2, count2);
+ }
+ }
+
+ // TODO https://github.com/dotnet/coreclr/issues/13827:
+ // This method shouldn't be necessary, as we should be able to just use the overload
+ // that takes two spans. But due to this issue, that's adding significant overhead.
+ private unsafe int CompareString(ReadOnlySpan<char> string1, string string2, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(string2 != null);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
+ fixed (char* pString2 = &string2.GetRawStringData())
+ {
+ return Interop.Globalization.CompareString(_sortHandle, pString1, string1.Length, pString2, string2.Length, options);
+ }
+ }
+
+ private unsafe int CompareString(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
+ fixed (char* pString2 = &MemoryMarshal.GetReference(string2))
+ {
+ return Interop.Globalization.CompareString(_sortHandle, pString1, string1.Length, pString2, string2.Length, options);
+ }
+ }
+
+ internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(target != null);
+ Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ int index;
+
+ if (target.Length == 0)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = 0;
+ return startIndex;
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ index = IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ if (index != -1)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ }
+ return index;
+ }
+
+#if CORECLR
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
+ {
+ index = IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
+ if (index != -1)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ }
+ return index;
+ }
+#endif
+
+ fixed (char* pSource = source)
+ fixed (char* pTarget = target)
+ {
+ index = Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource + startIndex, count, options, matchLengthPtr);
+
+ return index != -1 ? index + startIndex : -1;
+ }
+ }
+
+ // For now, this method is only called from Span APIs with either options == CompareOptions.None or CompareOptions.IgnoreCase
+ internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(source.Length != 0);
+ Debug.Assert(target.Length != 0);
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
+ {
+ if ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase)
+ return IndexOfOrdinalIgnoreCaseHelper(source, target, options, matchLengthPtr, fromBeginning);
+ else
+ return IndexOfOrdinalHelper(source, target, options, matchLengthPtr, fromBeginning);
+ }
+ else
+ {
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pTarget = &MemoryMarshal.GetReference(target))
+ {
+ if (fromBeginning)
+ return Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options, matchLengthPtr);
+ else
+ return Interop.Globalization.LastIndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Duplicate of IndexOfOrdinalHelper that also handles ignore case. Can't converge both methods
+ /// as the JIT wouldn't be able to optimize the ignoreCase path away.
+ /// </summary>
+ /// <returns></returns>
+ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!target.IsEmpty);
+ Debug.Assert(_isAsciiEqualityOrdinal);
+
+ fixed (char* ap = &MemoryMarshal.GetReference(source))
+ fixed (char* bp = &MemoryMarshal.GetReference(target))
+ {
+ char* a = ap;
+ char* b = bp;
+
+ if (target.Length > source.Length)
+ goto InteropCall;
+
+ for (int j = 0; j < target.Length; j++)
+ {
+ char targetChar = *(b + j);
+ if (targetChar >= 0x80 || s_highCharTable[targetChar])
+ goto InteropCall;
+ }
+
+ int startIndex, endIndex, jump;
+ if (fromBeginning)
+ {
+ // Left to right, from zero to last possible index in the source string.
+ // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
+ startIndex = 0;
+ endIndex = source.Length - target.Length + 1;
+ jump = 1;
+ }
+ else
+ {
+ // Right to left, from first possible index in the source string to zero.
+ // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
+ startIndex = source.Length - target.Length;
+ endIndex = -1;
+ jump = -1;
+ }
+
+ for (int i = startIndex; i != endIndex; i += jump)
+ {
+ int targetIndex = 0;
+ int sourceIndex = i;
+
+ for (; targetIndex < target.Length; targetIndex++, sourceIndex++)
+ {
+ char valueChar = *(a + sourceIndex);
+ char targetChar = *(b + targetIndex);
+
+ if (valueChar == targetChar && valueChar < 0x80 && !s_highCharTable[valueChar])
+ {
+ continue;
+ }
+
+ // uppercase both chars - notice that we need just one compare per char
+ if ((uint)(valueChar - 'a') <= ('z' - 'a'))
+ valueChar = (char)(valueChar - 0x20);
+ if ((uint)(targetChar - 'a') <= ('z' - 'a'))
+ targetChar = (char)(targetChar - 0x20);
+
+ if (valueChar >= 0x80 || s_highCharTable[valueChar])
+ goto InteropCall;
+ else if (valueChar != targetChar)
+ break;
+ }
+
+ if (targetIndex == target.Length)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ return i;
+ }
+ }
+
+ return -1;
+ InteropCall:
+ if (fromBeginning)
+ return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
+ else
+ return Interop.Globalization.LastIndexOf(_sortHandle, b, target.Length, a, source.Length, options);
+ }
+ }
+
+ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!target.IsEmpty);
+ Debug.Assert(_isAsciiEqualityOrdinal);
+
+ fixed (char* ap = &MemoryMarshal.GetReference(source))
+ fixed (char* bp = &MemoryMarshal.GetReference(target))
+ {
+ char* a = ap;
+ char* b = bp;
+
+ if (target.Length > source.Length)
+ goto InteropCall;
+
+ for (int j = 0; j < target.Length; j++)
+ {
+ char targetChar = *(b + j);
+ if (targetChar >= 0x80 || s_highCharTable[targetChar])
+ goto InteropCall;
+ }
+
+ int startIndex, endIndex, jump;
+ if (fromBeginning)
+ {
+ // Left to right, from zero to last possible index in the source string.
+ // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
+ startIndex = 0;
+ endIndex = source.Length - target.Length + 1;
+ jump = 1;
+ }
+ else
+ {
+ // Right to left, from first possible index in the source string to zero.
+ // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
+ startIndex = source.Length - target.Length;
+ endIndex = -1;
+ jump = -1;
+ }
+
+ for (int i = startIndex; i != endIndex; i += jump)
+ {
+ int targetIndex = 0;
+ int sourceIndex = i;
+
+ for (; targetIndex < target.Length; targetIndex++, sourceIndex++)
+ {
+ char valueChar = *(a + sourceIndex);
+ char targetChar = *(b + targetIndex);
+
+ if (valueChar >= 0x80 || s_highCharTable[valueChar])
+ goto InteropCall;
+ else if (valueChar != targetChar)
+ break;
+ }
+
+ if (targetIndex == target.Length)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ return i;
+ }
+ }
+
+ return -1;
+ InteropCall:
+ if (fromBeginning)
+ return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
+ else
+ return Interop.Globalization.LastIndexOf(_sortHandle, b, target.Length, a, source.Length, options);
+ }
+ }
+
+ private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(target != null);
+ Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ if (target.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return LastIndexOfOrdinalCore(source, target, startIndex, count, ignoreCase: false);
+ }
+
+#if CORECLR
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
+ {
+ return LastIndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
+ }
+#endif
+
+ // startIndex is the index into source where we start search backwards from. leftStartIndex is the index into source
+ // of the start of the string that is count characters away from startIndex.
+ int leftStartIndex = (startIndex - count + 1);
+
+ fixed (char* pSource = source)
+ fixed (char* pTarget = target)
+ {
+ int lastIndex = Interop.Globalization.LastIndexOf(_sortHandle, pTarget, target.Length, pSource + (startIndex - count + 1), count, options);
+
+ return lastIndex != -1 ? lastIndex + leftStartIndex : -1;
+ }
+ }
+
+ private bool StartsWith(string source, string prefix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(!string.IsNullOrEmpty(prefix));
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+#if CORECLR
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && prefix.IsFastSort())
+ {
+ return IsPrefix(source, prefix, GetOrdinalCompareOptions(options));
+ }
+#endif
+
+ return Interop.Globalization.StartsWith(_sortHandle, prefix, prefix.Length, source, source.Length, options);
+ }
+
+ private unsafe bool StartsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!prefix.IsEmpty);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
+ {
+ if (source.Length < prefix.Length)
+ {
+ return false;
+ }
+
+ if ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase)
+ {
+ return StartsWithOrdinalIgnoreCaseHelper(source, prefix, options);
+ }
+ else
+ {
+ return StartsWithOrdinalHelper(source, prefix, options);
+ }
+ }
+ else
+ {
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pPrefix = &MemoryMarshal.GetReference(prefix))
+ {
+ return Interop.Globalization.StartsWith(_sortHandle, pPrefix, prefix.Length, pSource, source.Length, options);
+ }
+ }
+ }
+
+ private unsafe bool StartsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!prefix.IsEmpty);
+ Debug.Assert(_isAsciiEqualityOrdinal);
+ Debug.Assert(source.Length >= prefix.Length);
+
+ int length = prefix.Length;
+
+ fixed (char* ap = &MemoryMarshal.GetReference(source))
+ fixed (char* bp = &MemoryMarshal.GetReference(prefix))
+ {
+ char* a = ap;
+ char* b = bp;
+
+ while (length != 0 && (*a < 0x80) && (*b < 0x80) && (!s_highCharTable[*a]) && (!s_highCharTable[*b]))
+ {
+ int charA = *a;
+ int charB = *b;
+
+ if (charA == charB)
+ {
+ a++; b++;
+ length--;
+ continue;
+ }
+
+ // uppercase both chars - notice that we need just one compare per char
+ if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
+ if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
+
+ if (charA != charB)
+ return false;
+
+ // Next char
+ a++; b++;
+ length--;
+ }
+
+ if (length == 0) return true;
+ return Interop.Globalization.StartsWith(_sortHandle, b, length, a, length, options);
+ }
+ }
+
+ private unsafe bool StartsWithOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!prefix.IsEmpty);
+ Debug.Assert(_isAsciiEqualityOrdinal);
+ Debug.Assert(source.Length >= prefix.Length);
+
+ int length = prefix.Length;
+
+ fixed (char* ap = &MemoryMarshal.GetReference(source))
+ fixed (char* bp = &MemoryMarshal.GetReference(prefix))
+ {
+ char* a = ap;
+ char* b = bp;
+
+ while (length != 0 && (*a < 0x80) && (*b < 0x80) && (!s_highCharTable[*a]) && (!s_highCharTable[*b]))
+ {
+ int charA = *a;
+ int charB = *b;
+
+ if (charA != charB)
+ return false;
+
+ // Next char
+ a++; b++;
+ length--;
+ }
+
+ if (length == 0) return true;
+ return Interop.Globalization.StartsWith(_sortHandle, b, length, a, length, options);
+ }
+ }
+
+ private bool EndsWith(string source, string suffix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(!string.IsNullOrEmpty(suffix));
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+#if CORECLR
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && suffix.IsFastSort())
+ {
+ return IsSuffix(source, suffix, GetOrdinalCompareOptions(options));
+ }
+#endif
+
+ return Interop.Globalization.EndsWith(_sortHandle, suffix, suffix.Length, source, source.Length, options);
+ }
+
+ private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!suffix.IsEmpty);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
+ {
+ if (source.Length < suffix.Length)
+ {
+ return false;
+ }
+
+ if ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase)
+ {
+ return EndsWithOrdinalIgnoreCaseHelper(source, suffix, options);
+ }
+ else
+ {
+ return EndsWithOrdinalHelper(source, suffix, options);
+ }
+ }
+ else
+ {
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pSuffix = &MemoryMarshal.GetReference(suffix))
+ {
+ return Interop.Globalization.EndsWith(_sortHandle, pSuffix, suffix.Length, pSource, source.Length, options);
+ }
+ }
+ }
+
+ private unsafe bool EndsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!suffix.IsEmpty);
+ Debug.Assert(_isAsciiEqualityOrdinal);
+ Debug.Assert(source.Length >= suffix.Length);
+
+ int length = suffix.Length;
+
+ fixed (char* ap = &MemoryMarshal.GetReference(source))
+ fixed (char* bp = &MemoryMarshal.GetReference(suffix))
+ {
+ char* a = ap + source.Length - 1;
+ char* b = bp + suffix.Length - 1;
+
+ while (length != 0 && (*a < 0x80) && (*b < 0x80) && (!s_highCharTable[*a]) && (!s_highCharTable[*b]))
+ {
+ int charA = *a;
+ int charB = *b;
+
+ if (charA == charB)
+ {
+ a--; b--;
+ length--;
+ continue;
+ }
+
+ // uppercase both chars - notice that we need just one compare per char
+ if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
+ if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
+
+ if (charA != charB)
+ return false;
+
+ // Next char
+ a--; b--;
+ length--;
+ }
+
+ if (length == 0) return true;
+ return Interop.Globalization.EndsWith(_sortHandle, b - length + 1, length, a - length + 1, length, options);
+ }
+ }
+
+ private unsafe bool EndsWithOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!suffix.IsEmpty);
+ Debug.Assert(_isAsciiEqualityOrdinal);
+ Debug.Assert(source.Length >= suffix.Length);
+
+ int length = suffix.Length;
+
+ fixed (char* ap = &MemoryMarshal.GetReference(source))
+ fixed (char* bp = &MemoryMarshal.GetReference(suffix))
+ {
+ char* a = ap + source.Length - 1;
+ char* b = bp + suffix.Length - 1;
+
+ while (length != 0 && (*a < 0x80) && (*b < 0x80) && (!s_highCharTable[*a]) && (!s_highCharTable[*b]))
+ {
+ int charA = *a;
+ int charB = *b;
+
+ if (charA != charB)
+ return false;
+
+ // Next char
+ a--; b--;
+ length--;
+ }
+
+ if (length == 0) return true;
+ return Interop.Globalization.EndsWith(_sortHandle, b - length + 1, length, a - length + 1, length, options);
+ }
+ }
+
+ private unsafe SortKey CreateSortKey(string source, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ if (source==null) { throw new ArgumentNullException(nameof(source)); }
+
+ if ((options & ValidSortkeyCtorMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
+ }
+
+ byte [] keyData;
+ if (source.Length == 0)
+ {
+ keyData = Array.Empty<Byte>();
+ }
+ else
+ {
+ int sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, null, 0, options);
+ keyData = new byte[sortKeyLength];
+
+ fixed (byte* pSortKey = keyData)
+ {
+ if (Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+ }
+ }
+
+ return new SortKey(Name, source, options, keyData);
+ }
+
+ private static unsafe bool IsSortable(char *text, int length)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ int index = 0;
+ UnicodeCategory uc;
+
+ while (index < length)
+ {
+ if (char.IsHighSurrogate(text[index]))
+ {
+ if (index == length - 1 || !char.IsLowSurrogate(text[index+1]))
+ return false; // unpaired surrogate
+
+ uc = CharUnicodeInfo.GetUnicodeCategory(char.ConvertToUtf32(text[index], text[index+1]));
+ if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned)
+ return false;
+
+ index += 2;
+ continue;
+ }
+
+ if (char.IsLowSurrogate(text[index]))
+ {
+ return false; // unpaired surrogate
+ }
+
+ uc = CharUnicodeInfo.GetUnicodeCategory(text[index]);
+ if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned)
+ {
+ return false;
+ }
+
+ index++;
+ }
+
+ return true;
+ }
+
+ // -----------------------------
+ // ---- PAL layer ends here ----
+ // -----------------------------
+
+ internal unsafe int GetHashCodeOfStringCore(string source, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(source != null);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (source.Length == 0)
+ {
+ return 0;
+ }
+
+ int sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, null, 0, options);
+
+ byte[] borrowedArr = null;
+ Span<byte> span = sortKeyLength <= 512 ?
+ stackalloc byte[512] :
+ (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
+
+ fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
+ {
+ if (Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+ }
+
+ int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
+
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
+ {
+ ArrayPool<byte>.Shared.Return(borrowedArr);
+ }
+
+ return hash;
+ }
+
+ private static CompareOptions GetOrdinalCompareOptions(CompareOptions options)
+ {
+ if ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase)
+ {
+ return CompareOptions.OrdinalIgnoreCase;
+ }
+ else
+ {
+ return CompareOptions.Ordinal;
+ }
+ }
+
+ private static bool CanUseAsciiOrdinalForOptions(CompareOptions options)
+ {
+ // Unlike the other Ignore options, IgnoreSymbols impacts ASCII characters (e.g. ').
+ return (options & CompareOptions.IgnoreSymbols) == 0;
+ }
+
+ private static byte[] GetNullTerminatedUtf8String(string s)
+ {
+ int byteLen = System.Text.Encoding.UTF8.GetByteCount(s);
+
+ // Allocate an extra byte (which defaults to 0) as the null terminator.
+ byte[] buffer = new byte[byteLen + 1];
+
+ int bytesWritten = System.Text.Encoding.UTF8.GetBytes(s, 0, s.Length, buffer, 0);
+
+ Debug.Assert(bytesWritten == byteLen);
+
+ return buffer;
+ }
+
+ private SortVersion GetSortVersion()
+ {
+ Debug.Assert(!_invariantMode);
+
+ int sortVersion = Interop.Globalization.GetSortVersion(_sortHandle);
+ return new SortVersion(sortVersion, LCID, new Guid(sortVersion, 0, 0, 0, 0, 0, 0,
+ (byte) (LCID >> 24),
+ (byte) ((LCID & 0x00FF0000) >> 16),
+ (byte) ((LCID & 0x0000FF00) >> 8),
+ (byte) (LCID & 0xFF)));
+ }
+
+ // See https://github.com/dotnet/coreclr/blob/master/src/utilcode/util_nodependencies.cpp#L970
+ private static readonly bool[] s_highCharTable = new bool[0x80]
+ {
+ true, /* 0x0, 0x0 */
+ true, /* 0x1, .*/
+ true, /* 0x2, .*/
+ true, /* 0x3, .*/
+ true, /* 0x4, .*/
+ true, /* 0x5, .*/
+ true, /* 0x6, .*/
+ true, /* 0x7, .*/
+ true, /* 0x8, .*/
+ false, /* 0x9, */
+ true, /* 0xA, */
+ false, /* 0xB, .*/
+ false, /* 0xC, .*/
+ true, /* 0xD, */
+ true, /* 0xE, .*/
+ true, /* 0xF, .*/
+ true, /* 0x10, .*/
+ true, /* 0x11, .*/
+ true, /* 0x12, .*/
+ true, /* 0x13, .*/
+ true, /* 0x14, .*/
+ true, /* 0x15, .*/
+ true, /* 0x16, .*/
+ true, /* 0x17, .*/
+ true, /* 0x18, .*/
+ true, /* 0x19, .*/
+ true, /* 0x1A, */
+ true, /* 0x1B, .*/
+ true, /* 0x1C, .*/
+ true, /* 0x1D, .*/
+ true, /* 0x1E, .*/
+ true, /* 0x1F, .*/
+ false, /*0x20, */
+ false, /*0x21, !*/
+ false, /*0x22, "*/
+ false, /*0x23, #*/
+ false, /*0x24, $*/
+ false, /*0x25, %*/
+ false, /*0x26, &*/
+ true, /*0x27, '*/
+ false, /*0x28, (*/
+ false, /*0x29, )*/
+ false, /*0x2A **/
+ false, /*0x2B, +*/
+ false, /*0x2C, ,*/
+ true, /*0x2D, -*/
+ false, /*0x2E, .*/
+ false, /*0x2F, /*/
+ false, /*0x30, 0*/
+ false, /*0x31, 1*/
+ false, /*0x32, 2*/
+ false, /*0x33, 3*/
+ false, /*0x34, 4*/
+ false, /*0x35, 5*/
+ false, /*0x36, 6*/
+ false, /*0x37, 7*/
+ false, /*0x38, 8*/
+ false, /*0x39, 9*/
+ false, /*0x3A, :*/
+ false, /*0x3B, ;*/
+ false, /*0x3C, <*/
+ false, /*0x3D, =*/
+ false, /*0x3E, >*/
+ false, /*0x3F, ?*/
+ false, /*0x40, @*/
+ false, /*0x41, A*/
+ false, /*0x42, B*/
+ false, /*0x43, C*/
+ false, /*0x44, D*/
+ false, /*0x45, E*/
+ false, /*0x46, F*/
+ false, /*0x47, G*/
+ false, /*0x48, H*/
+ false, /*0x49, I*/
+ false, /*0x4A, J*/
+ false, /*0x4B, K*/
+ false, /*0x4C, L*/
+ false, /*0x4D, M*/
+ false, /*0x4E, N*/
+ false, /*0x4F, O*/
+ false, /*0x50, P*/
+ false, /*0x51, Q*/
+ false, /*0x52, R*/
+ false, /*0x53, S*/
+ false, /*0x54, T*/
+ false, /*0x55, U*/
+ false, /*0x56, V*/
+ false, /*0x57, W*/
+ false, /*0x58, X*/
+ false, /*0x59, Y*/
+ false, /*0x5A, Z*/
+ false, /*0x5B, [*/
+ false, /*0x5C, \*/
+ false, /*0x5D, ]*/
+ false, /*0x5E, ^*/
+ false, /*0x5F, _*/
+ false, /*0x60, `*/
+ false, /*0x61, a*/
+ false, /*0x62, b*/
+ false, /*0x63, c*/
+ false, /*0x64, d*/
+ false, /*0x65, e*/
+ false, /*0x66, f*/
+ false, /*0x67, g*/
+ false, /*0x68, h*/
+ false, /*0x69, i*/
+ false, /*0x6A, j*/
+ false, /*0x6B, k*/
+ false, /*0x6C, l*/
+ false, /*0x6D, m*/
+ false, /*0x6E, n*/
+ false, /*0x6F, o*/
+ false, /*0x70, p*/
+ false, /*0x71, q*/
+ false, /*0x72, r*/
+ false, /*0x73, s*/
+ false, /*0x74, t*/
+ false, /*0x75, u*/
+ false, /*0x76, v*/
+ false, /*0x77, w*/
+ false, /*0x78, x*/
+ false, /*0x79, y*/
+ false, /*0x7A, z*/
+ false, /*0x7B, {*/
+ false, /*0x7C, |*/
+ false, /*0x7D, }*/
+ false, /*0x7E, ~*/
+ true, /*0x7F, */
+ };
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs
new file mode 100644
index 000000000..d1b12c664
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs
@@ -0,0 +1,647 @@
+// 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.Buffers;
+using System.Diagnostics;
+using System.Security;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System.Globalization
+{
+ public partial class CompareInfo
+ {
+ private unsafe void InitSort(CultureInfo culture)
+ {
+ _sortName = culture.SortName;
+
+ if (_invariantMode)
+ {
+ _sortHandle = IntPtr.Zero;
+ }
+ else
+ {
+ const uint LCMAP_SORTHANDLE = 0x20000000;
+
+ IntPtr handle;
+ int ret = Interop.Kernel32.LCMapStringEx(_sortName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero);
+ _sortHandle = ret > 0 ? handle : IntPtr.Zero;
+ }
+ }
+
+ private static unsafe int FindStringOrdinal(
+ uint dwFindStringOrdinalFlags,
+ string stringSource,
+ int offset,
+ int cchSource,
+ string value,
+ int cchValue,
+ bool bIgnoreCase)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(stringSource != null);
+ Debug.Assert(value != null);
+
+ fixed (char* pSource = stringSource)
+ fixed (char* pValue = value)
+ {
+ int ret = Interop.Kernel32.FindStringOrdinal(
+ dwFindStringOrdinalFlags,
+ pSource + offset,
+ cchSource,
+ pValue,
+ cchValue,
+ bIgnoreCase ? 1 : 0);
+ return ret < 0 ? ret : ret + offset;
+ }
+ }
+
+ private static unsafe int FindStringOrdinal(
+ uint dwFindStringOrdinalFlags,
+ ReadOnlySpan<char> source,
+ ReadOnlySpan<char> value,
+ bool bIgnoreCase)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pValue = &MemoryMarshal.GetReference(value))
+ {
+ int ret = Interop.Kernel32.FindStringOrdinal(
+ dwFindStringOrdinalFlags,
+ pSource,
+ source.Length,
+ pValue,
+ value.Length,
+ bIgnoreCase ? 1 : 0);
+ return ret;
+ }
+ }
+
+ internal static int IndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ Debug.Assert(source != null);
+ Debug.Assert(value != null);
+
+ return FindStringOrdinal(FIND_FROMSTART, source, startIndex, count, value, value.Length, ignoreCase);
+ }
+
+ internal static int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ Debug.Assert(source.Length != 0);
+ Debug.Assert(value.Length != 0);
+
+ uint positionFlag = fromBeginning ? (uint)FIND_FROMSTART : FIND_FROMEND;
+ return FindStringOrdinal(positionFlag, source, value, ignoreCase);
+ }
+
+ internal static int LastIndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ Debug.Assert(source != null);
+ Debug.Assert(value != null);
+
+ return FindStringOrdinal(FIND_FROMEND, source, startIndex - count + 1, count, value, value.Length, ignoreCase);
+ }
+
+ private unsafe int GetHashCodeOfStringCore(string source, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(source != null);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (source.Length == 0)
+ {
+ return 0;
+ }
+
+ uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
+
+ fixed (char* pSource = source)
+ {
+ int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
+ pSource, source.Length,
+ null, 0,
+ null, null, _sortHandle);
+ if (sortKeyLength == 0)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+
+ byte[] borrowedArr = null;
+ Span<byte> span = sortKeyLength <= 512 ?
+ stackalloc byte[512] :
+ (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
+
+ fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
+ {
+ if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
+ pSource, source.Length,
+ pSortKey, sortKeyLength,
+ null, null, _sortHandle) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+ }
+
+ int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
+
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
+ {
+ ArrayPool<byte>.Shared.Return(borrowedArr);
+ }
+
+ return hash;
+ }
+ }
+
+ private static unsafe int CompareStringOrdinalIgnoreCase(ref char string1, int count1, ref char string2, int count2)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ fixed (char* char1 = &string1)
+ fixed (char* char2 = &string2)
+ {
+ // Use the OS to compare and then convert the result to expected value by subtracting 2
+ return Interop.Kernel32.CompareStringOrdinal(char1, count1, char2, count2, true) - 2;
+ }
+ }
+
+ // TODO https://github.com/dotnet/coreclr/issues/13827:
+ // This method shouldn't be necessary, as we should be able to just use the overload
+ // that takes two spans. But due to this issue, that's adding significant overhead.
+ private unsafe int CompareString(ReadOnlySpan<char> string1, string string2, CompareOptions options)
+ {
+ Debug.Assert(string2 != null);
+ Debug.Assert(!_invariantMode);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
+
+ fixed (char* pLocaleName = localeName)
+ fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
+ fixed (char* pString2 = &string2.GetRawStringData())
+ {
+ Debug.Assert(pString1 != null);
+ int result = Interop.Kernel32.CompareStringEx(
+ pLocaleName,
+ (uint)GetNativeCompareFlags(options),
+ pString1,
+ string1.Length,
+ pString2,
+ string2.Length,
+ null,
+ null,
+ _sortHandle);
+
+ if (result == 0)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+
+ // Map CompareStringEx return value to -1, 0, 1.
+ return result - 2;
+ }
+ }
+
+ private unsafe int CompareString(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
+
+ fixed (char* pLocaleName = localeName)
+ fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
+ fixed (char* pString2 = &MemoryMarshal.GetReference(string2))
+ {
+ Debug.Assert(pString1 != null);
+ Debug.Assert(pString2 != null);
+ int result = Interop.Kernel32.CompareStringEx(
+ pLocaleName,
+ (uint)GetNativeCompareFlags(options),
+ pString1,
+ string1.Length,
+ pString2,
+ string2.Length,
+ null,
+ null,
+ _sortHandle);
+
+ if (result == 0)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+
+ // Map CompareStringEx return value to -1, 0, 1.
+ return result - 2;
+ }
+ }
+
+ private unsafe int FindString(
+ uint dwFindNLSStringFlags,
+ ReadOnlySpan<char> lpStringSource,
+ ReadOnlySpan<char> lpStringValue,
+ int* pcchFound)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(!lpStringSource.IsEmpty);
+ Debug.Assert(!lpStringValue.IsEmpty);
+
+ string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
+
+ fixed (char* pLocaleName = localeName)
+ fixed (char* pSource = &MemoryMarshal.GetReference(lpStringSource))
+ fixed (char* pValue = &MemoryMarshal.GetReference(lpStringValue))
+ {
+ return Interop.Kernel32.FindNLSStringEx(
+ pLocaleName,
+ dwFindNLSStringFlags,
+ pSource,
+ lpStringSource.Length,
+ pValue,
+ lpStringValue.Length,
+ pcchFound,
+ null,
+ null,
+ _sortHandle);
+ }
+ }
+
+ private unsafe int FindString(
+ uint dwFindNLSStringFlags,
+ string lpStringSource,
+ int startSource,
+ int cchSource,
+ string lpStringValue,
+ int startValue,
+ int cchValue,
+ int* pcchFound)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(lpStringSource != null);
+ Debug.Assert(lpStringValue != null);
+
+ string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
+
+ fixed (char* pLocaleName = localeName)
+ fixed (char* pSource = lpStringSource)
+ fixed (char* pValue = lpStringValue)
+ {
+ char* pS = pSource + startSource;
+ char* pV = pValue + startValue;
+
+ return Interop.Kernel32.FindNLSStringEx(
+ pLocaleName,
+ dwFindNLSStringFlags,
+ pS,
+ cchSource,
+ pV,
+ cchValue,
+ pcchFound,
+ null,
+ null,
+ _sortHandle);
+ }
+ }
+
+ internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(source != null);
+ Debug.Assert(target != null);
+ Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ if (target.Length == 0)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = 0;
+ return startIndex;
+ }
+
+ if (source.Length == 0)
+ {
+ return -1;
+ }
+
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ int retValue = FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false);
+ if (retValue >= 0)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ }
+ return retValue;
+ }
+ else
+ {
+ int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, startIndex, count,
+ target, 0, target.Length, matchLengthPtr);
+ if (retValue >= 0)
+ {
+ return retValue + startIndex;
+ }
+ }
+
+ return -1;
+ }
+
+ internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(source.Length != 0);
+ Debug.Assert(target.Length != 0);
+ Debug.Assert((options == CompareOptions.None || options == CompareOptions.IgnoreCase));
+
+ uint positionFlag = fromBeginning ? (uint)FIND_FROMSTART : FIND_FROMEND;
+ return FindString(positionFlag | (uint)GetNativeCompareFlags(options), source, target, matchLengthPtr);
+ }
+
+ private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(target != null);
+ Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ if (target.Length == 0)
+ return startIndex;
+
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ return FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: true);
+ }
+ else
+ {
+ int retValue = FindString(FIND_FROMEND | (uint)GetNativeCompareFlags(options), source, startIndex - count + 1,
+ count, target, 0, target.Length, null);
+
+ if (retValue >= 0)
+ {
+ return retValue + startIndex - (count - 1);
+ }
+ }
+
+ return -1;
+ }
+
+ private unsafe bool StartsWith(string source, string prefix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(!string.IsNullOrEmpty(prefix));
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length,
+ prefix, 0, prefix.Length, null) >= 0;
+ }
+
+ private unsafe bool StartsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!prefix.IsEmpty);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, prefix, null) >= 0;
+ }
+
+ private unsafe bool EndsWith(string source, string suffix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(!string.IsNullOrEmpty(suffix));
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length,
+ suffix, 0, suffix.Length, null) >= 0;
+ }
+
+ private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!suffix.IsEmpty);
+ Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, suffix, null) >= 0;
+ }
+
+ // PAL ends here
+ [NonSerialized]
+ private IntPtr _sortHandle;
+
+ private const uint LCMAP_SORTKEY = 0x00000400;
+ private const uint LCMAP_HASH = 0x00040000;
+
+ private const int FIND_STARTSWITH = 0x00100000;
+ private const int FIND_ENDSWITH = 0x00200000;
+ private const int FIND_FROMSTART = 0x00400000;
+ private const int FIND_FROMEND = 0x00800000;
+
+ // TODO: Instead of this method could we just have upstack code call IndexOfOrdinal with ignoreCase = false?
+ private static unsafe int FastIndexOfString(string source, string target, int startIndex, int sourceCount, int targetCount, bool findLastIndex)
+ {
+ int retValue = -1;
+
+ int sourceStartIndex = findLastIndex ? startIndex - sourceCount + 1 : startIndex;
+
+ fixed (char* pSource = source, spTarget = target)
+ {
+ char* spSubSource = pSource + sourceStartIndex;
+
+ if (findLastIndex)
+ {
+ int startPattern = (sourceCount - 1) - targetCount + 1;
+ if (startPattern < 0)
+ return -1;
+
+ char patternChar0 = spTarget[0];
+ for (int ctrSrc = startPattern; ctrSrc >= 0; ctrSrc--)
+ {
+ if (spSubSource[ctrSrc] != patternChar0)
+ continue;
+
+ int ctrPat;
+ for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
+ {
+ if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
+ break;
+ }
+ if (ctrPat == targetCount)
+ {
+ retValue = ctrSrc;
+ break;
+ }
+ }
+
+ if (retValue >= 0)
+ {
+ retValue += startIndex - sourceCount + 1;
+ }
+ }
+ else
+ {
+ int endPattern = (sourceCount - 1) - targetCount + 1;
+ if (endPattern < 0)
+ return -1;
+
+ char patternChar0 = spTarget[0];
+ for (int ctrSrc = 0; ctrSrc <= endPattern; ctrSrc++)
+ {
+ if (spSubSource[ctrSrc] != patternChar0)
+ continue;
+ int ctrPat;
+ for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
+ {
+ if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
+ break;
+ }
+ if (ctrPat == targetCount)
+ {
+ retValue = ctrSrc;
+ break;
+ }
+ }
+
+ if (retValue >= 0)
+ {
+ retValue += startIndex;
+ }
+ }
+ }
+
+ return retValue;
+ }
+
+ private unsafe SortKey CreateSortKey(string source, CompareOptions options)
+ {
+ Debug.Assert(!_invariantMode);
+
+ if (source == null) { throw new ArgumentNullException(nameof(source)); }
+
+ if ((options & ValidSortkeyCtorMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
+ }
+
+ byte [] keyData = null;
+ if (source.Length == 0)
+ {
+ keyData = Array.Empty<byte>();
+ }
+ else
+ {
+ uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
+
+ fixed (char *pSource = source)
+ {
+ int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
+ pSource, source.Length,
+ null, 0,
+ null, null, _sortHandle);
+ if (sortKeyLength == 0)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+
+ keyData = new byte[sortKeyLength];
+
+ fixed (byte* pBytes = keyData)
+ {
+ if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
+ pSource, source.Length,
+ pBytes, keyData.Length,
+ null, null, _sortHandle) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+ }
+ }
+ }
+
+ return new SortKey(Name, source, options, keyData);
+ }
+
+ private static unsafe bool IsSortable(char* text, int length)
+ {
+ Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(text != null);
+
+ return Interop.Kernel32.IsNLSDefinedString(Interop.Kernel32.COMPARE_STRING, 0, IntPtr.Zero, text, length);
+ }
+
+ private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal
+ private const int NORM_IGNORECASE = 0x00000001; // Ignores case. (use LINGUISTIC_IGNORECASE instead)
+ private const int NORM_IGNOREKANATYPE = 0x00010000; // Does not differentiate between Hiragana and Katakana characters. Corresponding Hiragana and Katakana will compare as equal.
+ private const int NORM_IGNORENONSPACE = 0x00000002; // Ignores nonspacing. This flag also removes Japanese accent characters. (use LINGUISTIC_IGNOREDIACRITIC instead)
+ private const int NORM_IGNORESYMBOLS = 0x00000004; // Ignores symbols.
+ private const int NORM_IGNOREWIDTH = 0x00020000; // Does not differentiate between a single-byte character and the same character as a double-byte character.
+ private const int NORM_LINGUISTIC_CASING = 0x08000000; // use linguistic rules for casing
+ private const int SORT_STRINGSORT = 0x00001000; // Treats punctuation the same as symbols.
+
+ private static int GetNativeCompareFlags(CompareOptions options)
+ {
+ // Use "linguistic casing" by default (load the culture's casing exception tables)
+ int nativeCompareFlags = NORM_LINGUISTIC_CASING;
+
+ if ((options & CompareOptions.IgnoreCase) != 0) { nativeCompareFlags |= NORM_IGNORECASE; }
+ if ((options & CompareOptions.IgnoreKanaType) != 0) { nativeCompareFlags |= NORM_IGNOREKANATYPE; }
+ if ((options & CompareOptions.IgnoreNonSpace) != 0) { nativeCompareFlags |= NORM_IGNORENONSPACE; }
+ if ((options & CompareOptions.IgnoreSymbols) != 0) { nativeCompareFlags |= NORM_IGNORESYMBOLS; }
+ if ((options & CompareOptions.IgnoreWidth) != 0) { nativeCompareFlags |= NORM_IGNOREWIDTH; }
+ if ((options & CompareOptions.StringSort) != 0) { nativeCompareFlags |= SORT_STRINGSORT; }
+
+ // TODO: Can we try for GetNativeCompareFlags to never
+ // take Ordinal or OrdinalIgnoreCase. This value is not part of Win32, we just handle it special
+ // in some places.
+ // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag
+ if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; }
+
+ Debug.Assert(((options & ~(CompareOptions.IgnoreCase |
+ CompareOptions.IgnoreKanaType |
+ CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreSymbols |
+ CompareOptions.IgnoreWidth |
+ CompareOptions.StringSort)) == 0) ||
+ (options == CompareOptions.Ordinal), "[CompareInfo.GetNativeCompareFlags]Expected all flags to be handled");
+
+ return nativeCompareFlags;
+ }
+
+ private unsafe SortVersion GetSortVersion()
+ {
+ Debug.Assert(!_invariantMode);
+
+ Interop.Kernel32.NlsVersionInfoEx nlsVersion = new Interop.Kernel32.NlsVersionInfoEx();
+ nlsVersion.dwNLSVersionInfoSize = sizeof(Interop.Kernel32.NlsVersionInfoEx);
+ Interop.Kernel32.GetNLSVersionEx(Interop.Kernel32.COMPARE_STRING, _sortName, &nlsVersion);
+ return new SortVersion(
+ nlsVersion.dwNLSVersion,
+ nlsVersion.dwEffectiveId == 0 ? LCID : nlsVersion.dwEffectiveId,
+ nlsVersion.guidCustomVersion);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
index c369c816b..92742c7b9 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
@@ -16,6 +16,8 @@ using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
+using System.Buffers;
+using Internal.Runtime.CompilerServices;
namespace System.Globalization
{
@@ -105,7 +107,7 @@ namespace System.Globalization
{
throw new ArgumentNullException(nameof(assembly));
}
- if (assembly != typeof(Object).Module.Assembly)
+ if (assembly != typeof(object).Module.Assembly)
{
throw new ArgumentException(SR.Argument_OnlyMscorlib);
}
@@ -132,7 +134,7 @@ namespace System.Globalization
throw new ArgumentNullException(name == null ? nameof(name) : nameof(assembly));
}
- if (assembly != typeof(Object).Module.Assembly)
+ if (assembly != typeof(object).Module.Assembly)
{
throw new ArgumentException(SR.Argument_OnlyMscorlib);
}
@@ -302,7 +304,7 @@ namespace System.Globalization
{
if (options == CompareOptions.OrdinalIgnoreCase)
{
- return String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
+ return string.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
}
// Verify the options before we do any real comparison.
@@ -313,7 +315,7 @@ namespace System.Globalization
throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
}
- return String.CompareOrdinal(string1, string2);
+ return string.CompareOrdinal(string1, string2);
}
if ((options & ValidCompareMaskOffFlags) != 0)
@@ -339,9 +341,9 @@ namespace System.Globalization
if (_invariantMode)
{
if ((options & CompareOptions.IgnoreCase) != 0)
- return CompareOrdinalIgnoreCase(string1, 0, string1.Length, string2, 0, string2.Length);
+ return CompareOrdinalIgnoreCase(string1, string2);
- return String.CompareOrdinal(string1, string2);
+ return string.CompareOrdinal(string1, string2);
}
return CompareString(string1.AsSpan(), string2.AsSpan(), options);
@@ -389,38 +391,26 @@ namespace System.Globalization
return CompareString(string1, string2, options);
}
- // TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
- internal virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
+ internal int CompareOptionNone(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
{
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return CompareOrdinalIgnoreCase(string1, string2);
- }
+ // Check for empty span or span from a null string
+ if (string1.Length == 0 || string2.Length == 0)
+ return string1.Length - string2.Length;
- // Verify the options before we do any real comparison.
- if ((options & CompareOptions.Ordinal) != 0)
- {
- if (options != CompareOptions.Ordinal)
- {
- throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
- }
-
- return string.CompareOrdinal(string1, string2);
- }
-
- if ((options & ValidCompareMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
+ return _invariantMode ?
+ string.CompareOrdinal(string1, string2) :
+ CompareString(string1, string2, CompareOptions.None);
+ }
- if (_invariantMode)
- {
- return (options & CompareOptions.IgnoreCase) != 0 ?
- CompareOrdinalIgnoreCase(string1, string2) :
- string.CompareOrdinal(string1, string2);
- }
+ internal int CompareOptionIgnoreCase(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
+ {
+ // Check for empty span or span from a null string
+ if (string1.Length == 0 || string2.Length == 0)
+ return string1.Length - string2.Length;
- return CompareString(string1, string2, options);
+ return _invariantMode ?
+ CompareOrdinalIgnoreCase(string1, string2) :
+ CompareString(string1, string2, CompareOptions.IgnoreCase);
}
////////////////////////////////////////////////////////////////////////
@@ -459,7 +449,7 @@ namespace System.Globalization
{
if (options == CompareOptions.OrdinalIgnoreCase)
{
- int result = String.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
+ int result = string.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
if ((length1 != length2) && result == 0)
return (length1 > length2 ? 1 : -1);
return (result);
@@ -511,35 +501,23 @@ namespace System.Globalization
return (1);
}
+ ReadOnlySpan<char> span1 = string1.AsSpan(offset1, length1);
+ ReadOnlySpan<char> span2 = string2.AsSpan(offset2, length2);
+
if (options == CompareOptions.Ordinal)
{
- return CompareOrdinal(string1, offset1, length1,
- string2, offset2, length2);
+ return string.CompareOrdinal(span1, span2);
}
if (_invariantMode)
{
if ((options & CompareOptions.IgnoreCase) != 0)
- return CompareOrdinalIgnoreCase(string1, offset1, length1, string2, offset2, length2);
+ return CompareOrdinalIgnoreCase(span1, span2);
- return CompareOrdinal(string1, offset1, length1, string2, offset2, length2);
+ return string.CompareOrdinal(span1, span2);
}
- return CompareString(
- string1.AsSpan().Slice(offset1, length1),
- string2.AsSpan().Slice(offset2, length2),
- options);
- }
-
- private static int CompareOrdinal(string string1, int offset1, int length1, string string2, int offset2, int length2)
- {
- int result = String.CompareOrdinal(string1, offset1, string2, offset2,
- (length1 < length2 ? length1 : length2));
- if ((length1 != length2) && result == 0)
- {
- return (length1 > length2 ? 1 : -1);
- }
- return (result);
+ return CompareString(span1, span2, options);
}
//
@@ -551,57 +529,103 @@ namespace System.Globalization
{
Debug.Assert(indexA + lengthA <= strA.Length);
Debug.Assert(indexB + lengthB <= strB.Length);
- return CompareOrdinalIgnoreCase(strA.AsSpan().Slice(indexA, lengthA), strB.AsSpan().Slice(indexB, lengthB));
+ return CompareOrdinalIgnoreCase(
+ ref Unsafe.Add(ref strA.GetRawStringData(), indexA),
+ lengthA,
+ ref Unsafe.Add(ref strB.GetRawStringData(), indexB),
+ lengthB);
}
- internal static unsafe int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
+ internal static int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
{
- int length = Math.Min(strA.Length, strB.Length);
+ return CompareOrdinalIgnoreCase(ref MemoryMarshal.GetReference(strA), strA.Length, ref MemoryMarshal.GetReference(strB), strB.Length);
+ }
+
+ internal static int CompareOrdinalIgnoreCase(string strA, string strB)
+ {
+ return CompareOrdinalIgnoreCase(ref strA.GetRawStringData(), strA.Length, ref strB.GetRawStringData(), strB.Length);
+ }
+
+ internal static int CompareOrdinalIgnoreCase(ref char strA, int lengthA, ref char strB, int lengthB)
+ {
+ int length = Math.Min(lengthA, lengthB);
int range = length;
- fixed (char* ap = &MemoryMarshal.GetReference(strA))
- fixed (char* bp = &MemoryMarshal.GetReference(strB))
- {
- char* a = ap;
- char* b = bp;
+ ref char charA = ref strA;
+ ref char charB = ref strB;
- // in InvariantMode we support all range and not only the ascii characters.
- char maxChar = (char) (GlobalizationMode.Invariant ? 0xFFFF : 0x7F);
+ // in InvariantMode we support all range and not only the ascii characters.
+ char maxChar = (GlobalizationMode.Invariant ? (char)0xFFFF : (char)0x7F);
- while (length != 0 && (*a <= maxChar) && (*b <= maxChar))
+ while (length != 0 && charA <= maxChar && charB <= maxChar)
+ {
+ // Ordinal equals or lowercase equals if the result ends up in the a-z range
+ if (charA == charB ||
+ ((charA | 0x20) == (charB | 0x20) &&
+ (uint)((charA | 0x20) - 'a') <= (uint)('z' - 'a')))
{
- int charA = *a;
- int charB = *b;
-
- if (charA == charB)
- {
- a++; b++;
- length--;
- continue;
- }
+ length--;
+ charA = ref Unsafe.Add(ref charA, 1);
+ charB = ref Unsafe.Add(ref charB, 1);
+ }
+ else
+ {
+ int currentA = charA;
+ int currentB = charB;
- // uppercase both chars - notice that we need just one compare per char
- if ((uint)(charA - 'a') <= 'z' - 'a') charA -= 0x20;
- if ((uint)(charB - 'a') <= 'z' - 'a') charB -= 0x20;
+ // Uppercase both chars if needed
+ if ((uint)(charA - 'a') <= 'z' - 'a')
+ currentA -= 0x20;
+ if ((uint)(charB - 'a') <= 'z' - 'a')
+ currentB -= 0x20;
// Return the (case-insensitive) difference between them.
- if (charA != charB)
- return charA - charB;
-
- // Next char
- a++; b++;
- length--;
+ return currentA - currentB;
}
+ }
+
+ if (length == 0)
+ return lengthA - lengthB;
+
+ Debug.Assert(!GlobalizationMode.Invariant);
- if (length == 0)
- return strA.Length - strB.Length;
+ range -= length;
- Debug.Assert(!GlobalizationMode.Invariant);
+ return CompareStringOrdinalIgnoreCase(ref charA, lengthA - range, ref charB, lengthB - range);
+ }
+
+
+ internal static bool EqualsOrdinalIgnoreCase(ref char strA, ref char strB, int length)
+ {
+ ref char charA = ref strA;
+ ref char charB = ref strB;
- range -= length;
+ // in InvariantMode we support all range and not only the ascii characters.
+ char maxChar = (GlobalizationMode.Invariant ? (char)0xFFFF : (char)0x7F);
- return CompareStringOrdinalIgnoreCase(a, strA.Length - range, b, strB.Length - range);
+ while (length != 0 && charA <= maxChar && charB <= maxChar)
+ {
+ // Ordinal equals or lowercase equals if the result ends up in the a-z range
+ if (charA == charB ||
+ ((charA | 0x20) == (charB | 0x20) &&
+ (uint)((charA | 0x20) - 'a') <= (uint)('z' - 'a')))
+ {
+ length--;
+ charA = ref Unsafe.Add(ref charA, 1);
+ charB = ref Unsafe.Add(ref charB, 1);
+ }
+ else
+ {
+ return false;
+ }
}
+
+ if (length == 0)
+ return true;
+
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ return CompareStringOrdinalIgnoreCase(ref charA, length, ref charB, length) == 0;
}
////////////////////////////////////////////////////////////////////////
@@ -609,7 +633,7 @@ namespace System.Globalization
// IsPrefix
//
// Determines whether prefix is a prefix of string. If prefix equals
- // String.Empty, true is returned.
+ // string.Empty, true is returned.
//
////////////////////////////////////////////////////////////////////////
public virtual bool IsPrefix(string source, string prefix, CompareOptions options)
@@ -674,7 +698,7 @@ namespace System.Globalization
// IsSuffix
//
// Determines whether suffix is a suffix of string. If suffix equals
- // String.Empty, true is returned.
+ // string.Empty, true is returned.
//
////////////////////////////////////////////////////////////////////////
public virtual bool IsSuffix(string source, string suffix, CompareOptions options)
@@ -741,7 +765,7 @@ namespace System.Globalization
//
// Returns the first index where value is found in string. The
// search starts from startIndex and ends at endIndex. Returns -1 if
- // the specified value is not found. If value equals String.Empty,
+ // the specified value is not found. If value equals string.Empty,
// startIndex is returned. Throws IndexOutOfRange if startIndex or
// endIndex is less than zero or greater than the length of string.
// Throws ArgumentException if value is null.
@@ -910,16 +934,36 @@ namespace System.Globalization
return IndexOfCore(source, value, startIndex, count, options, null);
}
- internal virtual int IndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ internal int IndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfOrdinalCore(source, value, ignoreCase, fromBeginning: true);
+ }
+
+ internal int LastIndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfOrdinalCore(source, value, ignoreCase, fromBeginning: false);
+ }
+
+ internal unsafe int IndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
{
Debug.Assert(!_invariantMode);
- return IndexOfOrdinalCore(source, value, ignoreCase);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfCore(source, value, options, null, fromBeginning: true);
}
- internal unsafe virtual int IndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
+ internal unsafe int LastIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
{
Debug.Assert(!_invariantMode);
- return IndexOfCore(source, value, options, null);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfCore(source, value, options, null, fromBeginning: false);
}
// The following IndexOf overload is mainly used by String.Replace. This overload assumes the parameters are already validated
@@ -985,7 +1029,7 @@ namespace System.Globalization
//
// Returns the last index where value is found in string. The
// search starts from startIndex and ends at endIndex. Returns -1 if
- // the specified value is not found. If value equals String.Empty,
+ // the specified value is not found. If value equals string.Empty,
// endIndex is returned. Throws IndexOutOfRange if startIndex or
// endIndex is less than zero or greater than the length of string.
// Throws ArgumentException if value is null.
@@ -993,7 +1037,7 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public virtual int LastIndexOf(String source, char value)
+ public virtual int LastIndexOf(string source, char value)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
@@ -1208,7 +1252,7 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
CompareInfo that = value as CompareInfo;
@@ -1237,6 +1281,34 @@ namespace System.Globalization
return (this.Name.GetHashCode());
}
+ internal static unsafe int GetIgnoreCaseHash(string source)
+ {
+ Debug.Assert(source != null, "source must not be null");
+
+ // Do not allocate on the stack if string is empty
+ if (source.Length == 0)
+ {
+ return source.GetHashCode();
+ }
+
+ char[] borrowedArr = null;
+ Span<char> span = source.Length <= 255 ?
+ stackalloc char[255] :
+ (borrowedArr = ArrayPool<char>.Shared.Rent(source.Length));
+
+ int charsWritten = source.AsSpan().ToUpperInvariant(span);
+
+ // Slice the array to the size returned by ToUpperInvariant.
+ int hash = Marvin.ComputeHash32(MemoryMarshal.AsBytes(span.Slice(0, charsWritten)), Marvin.DefaultSeed);
+
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
+ {
+ ArrayPool<char>.Shared.Return(borrowedArr);
+ }
+
+ return hash;
+ }
////////////////////////////////////////////////////////////////////////
//
@@ -1277,6 +1349,11 @@ namespace System.Globalization
throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
}
+ if (_invariantMode)
+ {
+ return ((options & CompareOptions.IgnoreCase) != 0) ? GetIgnoreCaseHash(source) : source.GetHashCode();
+ }
+
return GetHashCodeOfStringCore(source, options);
}
@@ -1294,7 +1371,7 @@ namespace System.Globalization
if (options == CompareOptions.OrdinalIgnoreCase)
{
- return TextInfo.GetHashCodeOrdinalIgnoreCase(source);
+ return GetIgnoreCaseHash(source);
}
//
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
index 3fce52792..4b21f2e7d 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
@@ -149,7 +149,7 @@ namespace System.Globalization
// Failed, just use empty string
StringBuilderCache.Release(sb);
Debug.Fail("[CultureData.GetLocaleInfo(LocaleStringData)] Failed");
- return String.Empty;
+ return string.Empty;
}
return StringBuilderCache.GetStringAndRelease(sb);
}
@@ -216,7 +216,7 @@ namespace System.Globalization
// Failed, just use empty string
StringBuilderCache.Release(sb);
Debug.Fail("[CultureData.GetTimeFormatString(bool shortFormat)] Failed");
- return String.Empty;
+ return string.Empty;
}
return ConvertIcuTimeFormatString(StringBuilderCache.GetStringAndRelease(sb));
@@ -227,19 +227,19 @@ namespace System.Globalization
return this.GetLocaleInfo(LocaleNumberData.FirstDayOfWeek);
}
- private String[] GetTimeFormats()
+ private string[] GetTimeFormats()
{
string format = GetTimeFormatString(false);
return new string[] { format };
}
- private String[] GetShortTimeFormats()
+ private string[] GetShortTimeFormats()
{
string format = GetTimeFormatString(true);
return new string[] { format };
}
- private static CultureData GetCultureDataFromRegionName(String regionName)
+ private static CultureData GetCultureDataFromRegionName(string regionName)
{
// no support to lookup by region name, other than the hard-coded list in CultureData
return null;
@@ -371,7 +371,7 @@ namespace System.Globalization
return Array.Empty<CultureInfo>();
}
- Char [] chars = new Char[bufferLength];
+ char [] chars = new char[bufferLength];
bufferLength = Interop.Globalization.GetLocales(chars, bufferLength);
if (bufferLength <= 0)
@@ -394,7 +394,7 @@ namespace System.Globalization
int length = (int) chars[index++];
if (index + length <= bufferLength)
{
- CultureInfo ci = CultureInfo.GetCultureInfo(new String(chars, index, length));
+ CultureInfo ci = CultureInfo.GetCultureInfo(new string(chars, index, length));
if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecificss && !ci.IsNeutralCulture))
{
list.Add(ci);
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
index 393f983bb..75f78620d 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
@@ -517,7 +517,7 @@ namespace System.Globalization
// Context for EnumCalendarInfoExEx callback.
- private class EnumLocaleData
+ private struct EnumLocaleData
{
public string regionName;
public string cultureName;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
index fda239c51..5eb9f44f8 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
@@ -2268,7 +2268,7 @@ namespace System.Globalization
for (int i = startIndex; i < format.Length; ++i)
{
// See if we have a time Part
- if (!inQuote && timeParts.IndexOf(format[i]) != -1)
+ if (!inQuote && timeParts.Contains(format[i]))
{
return i;
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
index 10e8b1f83..007aff7b9 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
@@ -18,28 +18,28 @@ namespace System.Globalization
{
}
- public CultureNotFoundException(String message)
+ public CultureNotFoundException(string message)
: base(message)
{
}
- public CultureNotFoundException(String paramName, String message)
+ public CultureNotFoundException(string paramName, string message)
: base(message, paramName)
{
}
- public CultureNotFoundException(String message, Exception innerException)
+ public CultureNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
}
- public CultureNotFoundException(String paramName, string invalidCultureName, String message)
+ public CultureNotFoundException(string paramName, string invalidCultureName, string message)
: base(message, paramName)
{
_invalidCultureName = invalidCultureName;
}
- public CultureNotFoundException(String message, string invalidCultureName, Exception innerException)
+ public CultureNotFoundException(string message, string invalidCultureName, Exception innerException)
: base(message, innerException)
{
_invalidCultureName = invalidCultureName;
@@ -81,7 +81,7 @@ namespace System.Globalization
get { return _invalidCultureName; }
}
- private static String DefaultMessage
+ private static string DefaultMessage
{
get
{
@@ -89,24 +89,24 @@ namespace System.Globalization
}
}
- private String FormatedInvalidCultureId
+ private string FormatedInvalidCultureId
{
get
{
return InvalidCultureId != null ?
- String.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) :
+ string.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) :
InvalidCultureName;
}
}
- public override String Message
+ public override string Message
{
get
{
- String s = base.Message;
+ string s = base.Message;
if (_invalidCultureId != null || _invalidCultureName != null)
{
- String valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId);
+ string valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId);
if (s == null)
{
return valueMessage;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
index 595fb5631..73fb0e9b3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
namespace System
{
@@ -133,8 +134,8 @@ namespace System
's', 't', 'T', 'u', 'U', 'y', 'Y',
};
- internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
- internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
+ internal const string RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+ internal const string RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
@@ -143,7 +144,7 @@ namespace System
internal static readonly string[] InvariantAbbreviatedDayNames = InvariantFormatInfo.AbbreviatedDayNames;
internal const string Gmt = "GMT";
- internal static String[] fixedNumberFormats = new String[] {
+ internal static string[] fixedNumberFormats = new string[] {
"0",
"00",
"000",
@@ -164,7 +165,7 @@ namespace System
// If the digits of the value is greater than len, no leading zero is added.
//
// Notes:
- // The function can format to Int32.MaxValue.
+ // The function can format to int.MaxValue.
//
////////////////////////////////////////////////////////////////////////////
internal static void FormatDigits(StringBuilder outputBuffer, int value, int len)
@@ -173,7 +174,7 @@ namespace System
FormatDigits(outputBuffer, value, len, false);
}
- internal unsafe static void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit)
+ internal static unsafe void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit)
{
Debug.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0");
@@ -222,7 +223,7 @@ namespace System
return (index - pos);
}
- private static String FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi)
+ private static string FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi)
{
Debug.Assert(dayOfWeek >= 0 && dayOfWeek <= 6, "dayOfWeek >= 0 && dayOfWeek <= 6");
if (repeat == 3)
@@ -234,7 +235,7 @@ namespace System
return (dtfi.GetDayName((DayOfWeek)dayOfWeek));
}
- private static String FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi)
+ private static string FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi)
{
Debug.Assert(month >= 1 && month <= 12, "month >=1 && month <= 12");
if (repeatCount == 3)
@@ -275,7 +276,7 @@ namespace System
Therefore, if we are in a regular year, we have to increment the month name if moth is greater or eqaul to 7.
*/
- private static String FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi)
+ private static string FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi)
{
Debug.Assert(repeatCount != 3 || repeatCount != 4, "repeateCount should be 3 or 4");
if (dtfi.Calendar.IsLeapYear(dtfi.Calendar.GetYear(time)))
@@ -346,7 +347,7 @@ namespace System
{
// Here we can't find the matching quote.
throw new FormatException(
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.Format_BadQuote, quoteChar));
}
@@ -668,7 +669,7 @@ namespace System
}
else
{
- String fmtPattern = "D" + tokenLen.ToString();
+ string fmtPattern = "D" + tokenLen.ToString();
result.Append(year.ToString(fmtPattern, CultureInfo.InvariantCulture));
}
}
@@ -764,10 +765,10 @@ namespace System
// output the 'z' famliy of formats, which output a the offset from UTC, e.g. "-07:30"
- private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset, ReadOnlySpan<char> format, Int32 tokenLen, Boolean timeOnly, StringBuilder result)
+ private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset, ReadOnlySpan<char> format, int tokenLen, bool timeOnly, StringBuilder result)
{
// See if the instance already has an offset
- Boolean dateTimeFormat = (offset == NullOffset);
+ bool dateTimeFormat = (offset == NullOffset);
if (dateTimeFormat)
{
// No offset. The instance is a DateTime and the output should be the local time zone
@@ -852,14 +853,20 @@ namespace System
offset = offset.Negate();
}
- AppendNumber(result, offset.Hours, 2);
+ Append2DigitNumber(result, offset.Hours);
result.Append(':');
- AppendNumber(result, offset.Minutes, 2);
+ Append2DigitNumber(result, offset.Minutes);
}
- internal static String GetRealFormat(ReadOnlySpan<char> format, DateTimeFormatInfo dtfi)
+ private static void Append2DigitNumber(StringBuilder result, int val)
{
- String realFormat = null;
+ result.Append((char)('0' + (val / 10)));
+ result.Append((char)('0' + (val % 10)));
+ }
+
+ internal static string GetRealFormat(ReadOnlySpan<char> format, DateTimeFormatInfo dtfi)
+ {
+ string realFormat = null;
switch (format[0])
{
@@ -924,7 +931,7 @@ namespace System
// This method also convert the dateTime if necessary (e.g. when the format is in Universal time),
// and change dtfi if necessary (e.g. when the format should use invariant culture).
//
- private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTime dateTime, ref DateTimeFormatInfo dtfi, ref TimeSpan offset)
+ private static string ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTime dateTime, ref DateTimeFormatInfo dtfi, ref TimeSpan offset)
{
switch (format[0])
{
@@ -981,19 +988,65 @@ namespace System
return GetRealFormat(format, dtfi);
}
- internal static String Format(DateTime dateTime, String format, DateTimeFormatInfo dtfi)
+ internal static string Format(DateTime dateTime, string format, IFormatProvider provider)
{
- return Format(dateTime, format, dtfi, NullOffset);
+ return Format(dateTime, format, provider, NullOffset);
}
- internal static string Format(DateTime dateTime, String format, DateTimeFormatInfo dtfi, TimeSpan offset) =>
- StringBuilderCache.GetStringAndRelease(FormatStringBuilder(dateTime, format, dtfi, offset));
+ internal static string Format(DateTime dateTime, string format, IFormatProvider provider, TimeSpan offset)
+ {
+ if (format != null && format.Length == 1)
+ {
+ // Optimize for these standard formats that are not affected by culture.
+ switch (format[0])
+ {
+ // Round trip format
+ case 'o':
+ case 'O':
+ const int MinFormatOLength = 27, MaxFormatOLength = 33;
+ Span<char> span = stackalloc char[MaxFormatOLength];
+ TryFormatO(dateTime, offset, span, out int ochars);
+ Debug.Assert(ochars >= MinFormatOLength && ochars <= MaxFormatOLength);
+ return span.Slice(0, ochars).ToString();
+
+ // RFC1123
+ case 'r':
+ case 'R':
+ const int FormatRLength = 29;
+ string str = string.FastAllocateString(FormatRLength);
+ TryFormatR(dateTime, offset, new Span<char>(ref str.GetRawStringData(), str.Length), out int rchars);
+ Debug.Assert(rchars == str.Length);
+ return str;
+ }
+ }
+
+ DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(provider);
+ return StringBuilderCache.GetStringAndRelease(FormatStringBuilder(dateTime, format, dtfi, offset));
+ }
- internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi) =>
- TryFormat(dateTime, destination, out charsWritten, format, dtfi, NullOffset);
+ internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider provider) =>
+ TryFormat(dateTime, destination, out charsWritten, format, provider, NullOffset);
- internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
+ internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider provider, TimeSpan offset)
{
+ if (format.Length == 1)
+ {
+ // Optimize for these standard formats that are not affected by culture.
+ switch (format[0])
+ {
+ // Round trip format
+ case 'o':
+ case 'O':
+ return TryFormatO(dateTime, offset, destination, out charsWritten);
+
+ // RFC1123
+ case 'r':
+ case 'R':
+ return TryFormatR(dateTime, offset, destination, out charsWritten);
+ }
+ }
+
+ DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(provider);
StringBuilder sb = FormatStringBuilder(dateTime, format, dtfi, offset);
bool success = sb.Length <= destination.Length;
@@ -1011,12 +1064,12 @@ namespace System
return success;
}
- internal static StringBuilder FormatStringBuilder(DateTime dateTime, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
+ private static StringBuilder FormatStringBuilder(DateTime dateTime, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
{
Debug.Assert(dtfi != null);
if (format.Length == 0)
{
- Boolean timeOnlySpecialCase = false;
+ bool timeOnlySpecialCase = false;
if (dateTime.Ticks < Calendar.TicksPerDay)
{
// If the time is less than 1 day, consider it as time of day.
@@ -1060,108 +1113,211 @@ namespace System
if (format.Length == 1)
{
- switch (format[0])
+ format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
+ }
+
+ return FormatCustomized(dateTime, format, dtfi, offset, result: null);
+ }
+
+ // Roundtrippable format. One of
+ // 012345678901234567890123456789012
+ // ---------------------------------
+ // 2017-06-12T05:30:45.7680000-07:00
+ // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
+ // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
+ private static bool TryFormatO(DateTime dateTime, TimeSpan offset, Span<char> destination, out int charsWritten)
+ {
+ const int MinimumBytesNeeded = 27;
+
+ int charsRequired = MinimumBytesNeeded;
+ DateTimeKind kind = DateTimeKind.Local;
+
+ if (offset == NullOffset)
+ {
+ kind = dateTime.Kind;
+ if (kind == DateTimeKind.Local)
{
- case 'O':
- case 'o':
- return FastFormatRoundtrip(dateTime, offset);
- case 'R':
- case 'r':
- return FastFormatRfc1123(dateTime, offset, dtfi);
+ offset = TimeZoneInfo.Local.GetUtcOffset(dateTime);
+ charsRequired += 6;
+ }
+ else if (kind == DateTimeKind.Utc)
+ {
+ charsRequired += 1;
}
+ }
+ else
+ {
+ charsRequired += 6;
+ }
- format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
+ if (destination.Length < charsRequired)
+ {
+ charsWritten = 0;
+ return false;
}
+ charsWritten = charsRequired;
+
+ // Hoist most of the bounds checks on destination.
+ { var unused = destination[MinimumBytesNeeded - 1]; }
+
+ WriteFourDecimalDigits((uint)dateTime.Year, destination, 0);
+ destination[4] = '-';
+ WriteTwoDecimalDigits((uint)dateTime.Month, destination, 5);
+ destination[7] = '-';
+ WriteTwoDecimalDigits((uint)dateTime.Day, destination, 8);
+ destination[10] = 'T';
+ WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 11);
+ destination[13] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 14);
+ destination[16] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Second, destination, 17);
+ destination[19] = '.';
+ WriteDigits((uint)((ulong)dateTime.Ticks % (ulong)TimeSpan.TicksPerSecond), destination.Slice(20, 7));
+
+ if (kind == DateTimeKind.Local)
+ {
+ char sign;
+ if (offset < default(TimeSpan) /* a "const" version of TimeSpan.Zero */)
+ {
+ sign = '-';
+ offset = TimeSpan.FromTicks(-offset.Ticks);
+ }
+ else
+ {
+ sign = '+';
+ }
- return FormatCustomized(dateTime, format, dtfi, offset, result: null);
+ // Writing the value backward allows the JIT to optimize by
+ // performing a single bounds check against buffer.
+ WriteTwoDecimalDigits((uint)offset.Minutes, destination, 31);
+ destination[30] = ':';
+ WriteTwoDecimalDigits((uint)offset.Hours, destination, 28);
+ destination[27] = sign;
+ }
+ else if (kind == DateTimeKind.Utc)
+ {
+ destination[27] = 'Z';
+ }
+
+ return true;
}
- internal static StringBuilder FastFormatRfc1123(DateTime dateTime, TimeSpan offset, DateTimeFormatInfo dtfi)
+ // Rfc1123
+ // 01234567890123456789012345678
+ // -----------------------------
+ // Tue, 03 Jan 2017 08:08:05 GMT
+ private static bool TryFormatR(DateTime dateTime, TimeSpan offset, Span<char> destination, out int charsWritten)
{
- // ddd, dd MMM yyyy HH:mm:ss GMT
- const int Rfc1123FormatLength = 29;
- StringBuilder result = StringBuilderCache.Acquire(Rfc1123FormatLength);
+ // Writing the check in this fashion elides all bounds checks on 'destination'
+ // for the remainder of the method.
+ if (28 >= (uint)destination.Length)
+ {
+ charsWritten = 0;
+ return false;
+ }
if (offset != NullOffset)
{
- // Convert to UTC invariants
+ // Convert to UTC invariants.
dateTime = dateTime - offset;
}
dateTime.GetDatePart(out int year, out int month, out int day);
- result.Append(InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek]);
- result.Append(',');
- result.Append(' ');
- AppendNumber(result, day, 2);
- result.Append(' ');
- result.Append(InvariantAbbreviatedMonthNames[month - 1]);
- result.Append(' ');
- AppendNumber(result, year, 4);
- result.Append(' ');
- AppendHHmmssTimeOfDay(result, dateTime);
- result.Append(' ');
- result.Append(Gmt);
- return result;
+ string dayAbbrev = InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek];
+ Debug.Assert(dayAbbrev.Length == 3);
+
+ string monthAbbrev = InvariantAbbreviatedMonthNames[month - 1];
+ Debug.Assert(monthAbbrev.Length == 3);
+
+ destination[0] = dayAbbrev[0];
+ destination[1] = dayAbbrev[1];
+ destination[2] = dayAbbrev[2];
+ destination[3] = ',';
+ destination[4] = ' ';
+ WriteTwoDecimalDigits((uint)day, destination, 5);
+ destination[7] = ' ';
+ destination[8] = monthAbbrev[0];
+ destination[9] = monthAbbrev[1];
+ destination[10] = monthAbbrev[2];
+ destination[11] = ' ';
+ WriteFourDecimalDigits((uint)year, destination, 12);
+ destination[16] = ' ';
+ WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 17);
+ destination[19] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 20);
+ destination[22] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Second, destination, 23);
+ destination[25] = ' ';
+ destination[26] = 'G';
+ destination[27] = 'M';
+ destination[28] = 'T';
+
+ charsWritten = 29;
+ return true;
}
- internal static StringBuilder FastFormatRoundtrip(DateTime dateTime, TimeSpan offset)
+ /// <summary>
+ /// Writes a value [ 00 .. 99 ] to the buffer starting at the specified offset.
+ /// This method performs best when the starting index is a constant literal.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteTwoDecimalDigits(uint value, Span<char> destination, int offset)
{
- // yyyy-MM-ddTHH:mm:ss.fffffffK
- const int roundTripFormatLength = 28;
- StringBuilder result = StringBuilderCache.Acquire(roundTripFormatLength);
+ Debug.Assert(0 <= value && value <= 99);
- dateTime.GetDatePart(out int year, out int month, out int day);
- AppendNumber(result, year, 4);
- result.Append('-');
- AppendNumber(result, month, 2);
- result.Append('-');
- AppendNumber(result, day, 2);
- result.Append('T');
- AppendHHmmssTimeOfDay(result, dateTime);
- result.Append('.');
+ uint temp = '0' + value;
+ value /= 10;
+ destination[offset + 1] = (char)(temp - (value * 10));
+ destination[offset] = (char)('0' + value);
+ }
- long fraction = dateTime.Ticks % TimeSpan.TicksPerSecond;
- AppendNumber(result, fraction, 7);
+ /// <summary>
+ /// Writes a value [ 0000 .. 9999 ] to the buffer starting at the specified offset.
+ /// This method performs best when the starting index is a constant literal.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteFourDecimalDigits(uint value, Span<char> buffer, int startingIndex = 0)
+ {
+ Debug.Assert(0 <= value && value <= 9999);
- FormatCustomizedRoundripTimeZone(dateTime, offset, result);
+ uint temp = '0' + value;
+ value /= 10;
+ buffer[startingIndex + 3] = (char)(temp - (value * 10));
- return result;
- }
+ temp = '0' + value;
+ value /= 10;
+ buffer[startingIndex + 2] = (char)(temp - (value * 10));
- private static void AppendHHmmssTimeOfDay(StringBuilder result, DateTime dateTime)
- {
- // HH:mm:ss
- AppendNumber(result, dateTime.Hour, 2);
- result.Append(':');
- AppendNumber(result, dateTime.Minute, 2);
- result.Append(':');
- AppendNumber(result, dateTime.Second, 2);
+ temp = '0' + value;
+ value /= 10;
+ buffer[startingIndex + 1] = (char)(temp - (value * 10));
+
+ buffer[startingIndex] = (char)('0' + value);
}
- internal static void AppendNumber(StringBuilder builder, long val, int digits)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteDigits(ulong value, Span<char> buffer)
{
- for (int i = 0; i < digits; i++)
- {
- builder.Append('0');
- }
+ // We can mutate the 'value' parameter since it's a copy-by-value local.
+ // It'll be used to represent the value left over after each division by 10.
- int index = 1;
- while (val > 0 && index <= digits)
+ for (int i = buffer.Length - 1; i >= 1; i--)
{
- builder[builder.Length - index] = (char)('0' + (val % 10));
- val = val / 10;
- index++;
+ ulong temp = '0' + value;
+ value /= 10;
+ buffer[i] = (char)(temp - (value * 10));
}
- Debug.Assert(val == 0, "DateTimeFormat.AppendNumber(): digits less than size of val");
+ Debug.Assert(value < 10);
+ buffer[0] = (char)('0' + value);
}
- internal static String[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi)
+ internal static string[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi)
{
Debug.Assert(dtfi != null);
- String[] allFormats = null;
- String[] results = null;
+ string[] allFormats = null;
+ string[] results = null;
switch (format)
{
@@ -1178,7 +1334,7 @@ namespace System
case 'y':
case 'Y':
allFormats = dtfi.GetAllDateTimePatterns(format);
- results = new String[allFormats.Length];
+ results = new string[allFormats.Length];
for (int i = 0; i < allFormats.Length; i++)
{
results[i] = Format(dateTime, allFormats[i], dtfi);
@@ -1187,7 +1343,7 @@ namespace System
case 'U':
DateTime universalTime = dateTime.ToUniversalTime();
allFormats = dtfi.GetAllDateTimePatterns(format);
- results = new String[allFormats.Length];
+ results = new string[allFormats.Length];
for (int i = 0; i < allFormats.Length; i++)
{
results[i] = Format(universalTime, allFormats[i], dtfi);
@@ -1203,7 +1359,7 @@ namespace System
case 'O':
case 's':
case 'u':
- results = new String[] { Format(dateTime, new String(format, 1), dtfi) };
+ results = new string[] { Format(dateTime, new string(format, 1), dtfi) };
break;
default:
throw new FormatException(SR.Format_InvalidString);
@@ -1211,19 +1367,19 @@ namespace System
return (results);
}
- internal static String[] GetAllDateTimes(DateTime dateTime, DateTimeFormatInfo dtfi)
+ internal static string[] GetAllDateTimes(DateTime dateTime, DateTimeFormatInfo dtfi)
{
- List<String> results = new List<String>(DEFAULT_ALL_DATETIMES_SIZE);
+ List<string> results = new List<string>(DEFAULT_ALL_DATETIMES_SIZE);
for (int i = 0; i < allStandardFormats.Length; i++)
{
- String[] strings = GetAllDateTimes(dateTime, allStandardFormats[i], dtfi);
+ string[] strings = GetAllDateTimes(dateTime, allStandardFormats[i], dtfi);
for (int j = 0; j < strings.Length; j++)
{
results.Add(strings[j]);
}
}
- String[] value = new String[results.Count];
+ string[] value = new string[results.Count];
results.CopyTo(0, value, 0, results.Count);
return (value);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
index faa0deac3..8fc6f7beb 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
@@ -58,10 +58,10 @@ namespace System.Globalization
private CultureData _cultureData;
// The culture name used to create this DTFI.
- private String _name = null;
+ private string _name = null;
// The language name of the culture used to create this DTFI.
- private String _langName = null;
+ private string _langName = null;
// CompareInfo usually used by the parser.
private CompareInfo _compareInfo = null;
@@ -73,28 +73,28 @@ namespace System.Globalization
// Caches for various properties.
//
- private String amDesignator = null;
- private String pmDesignator = null;
+ private string amDesignator = null;
+ private string pmDesignator = null;
- private String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
+ private string dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
- private String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
+ private string generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
- private String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
+ private string generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
- private String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
- private String monthDayPattern = null;
+ private string timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
+ private string monthDayPattern = null;
// added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM}
- private String dateTimeOffsetPattern = null;
+ private string dateTimeOffsetPattern = null;
//
// The following are constant values.
//
- private const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
+ private const string rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
// The sortable pattern is based on ISO 8601.
- private const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
- private const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
+ private const string sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
+ private const string universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
//
// The following are affected by calendar settings.
@@ -105,27 +105,27 @@ namespace System.Globalization
private int calendarWeekRule = -1;
- private String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
+ private string fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
- private String[] abbreviatedDayNames = null;
+ private string[] abbreviatedDayNames = null;
- private String[] m_superShortDayNames = null;
+ private string[] m_superShortDayNames = null;
- private String[] dayNames = null;
- private String[] abbreviatedMonthNames = null;
- private String[] monthNames = null;
+ private string[] dayNames = null;
+ private string[] abbreviatedMonthNames = null;
+ private string[] monthNames = null;
// Cache the genitive month names that we retrieve from the data table.
- private String[] genitiveMonthNames = null;
+ private string[] genitiveMonthNames = null;
// Cache the abbreviated genitive month names that we retrieve from the data table.
- private String[] m_genitiveAbbreviatedMonthNames = null;
+ private string[] m_genitiveAbbreviatedMonthNames = null;
// Cache the month names of a leap year that we retrieve from the data table.
- private String[] leapYearMonthNames = null;
+ private string[] leapYearMonthNames = null;
// For our "patterns" arrays we have 2 variables, a string and a string[]
//
@@ -134,23 +134,23 @@ namespace System.Globalization
// When we initially construct our string[], we set the string to string[0]
// The "default" Date/time patterns
- private String longDatePattern = null;
- private String shortDatePattern = null;
- private String yearMonthPattern = null;
- private String longTimePattern = null;
- private String shortTimePattern = null;
+ private string longDatePattern = null;
+ private string shortDatePattern = null;
+ private string yearMonthPattern = null;
+ private string longTimePattern = null;
+ private string shortTimePattern = null;
- private String[] allYearMonthPatterns = null;
+ private string[] allYearMonthPatterns = null;
- private String[] allShortDatePatterns = null;
- private String[] allLongDatePatterns = null;
- private String[] allShortTimePatterns = null;
- private String[] allLongTimePatterns = null;
+ private string[] allShortDatePatterns = null;
+ private string[] allLongDatePatterns = null;
+ private string[] allShortTimePatterns = null;
+ private string[] allLongTimePatterns = null;
// Cache the era names for this DateTimeFormatInfo instance.
- private String[] m_eraNames = null;
- private String[] m_abbrevEraNames = null;
- private String[] m_abbrevEnglishEraNames = null;
+ private string[] m_eraNames = null;
+ private string[] m_abbrevEraNames = null;
+ private string[] m_abbrevEnglishEraNames = null;
private CalendarId[] optionalCalendars = null;
@@ -164,7 +164,7 @@ namespace System.Globalization
private DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized;
- private String CultureName
+ private string CultureName
{
get
{
@@ -189,7 +189,7 @@ namespace System.Globalization
}
// TODO: This ignores other cultures that might want to do something similar
- private String LanguageName
+ private string LanguageName
{
get
{
@@ -261,9 +261,9 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- private String[] internalGetAbbreviatedMonthNames() => this.abbreviatedMonthNames ?? internalGetAbbreviatedMonthNamesCore();
+ private string[] internalGetAbbreviatedMonthNames() => this.abbreviatedMonthNames ?? internalGetAbbreviatedMonthNamesCore();
[MethodImpl(MethodImplOptions.NoInlining)]
- private String[] internalGetAbbreviatedMonthNamesCore()
+ private string[] internalGetAbbreviatedMonthNamesCore()
{
// Get the month names for our current calendar
this.abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID);
@@ -386,13 +386,13 @@ namespace System.Globalization
provider.GetFormat(typeof(DateTimeFormatInfo)) is DateTimeFormatInfo info2 ? info2 :
CurrentInfo; // Couldn't get anything, just use currentInfo as fallback
- public Object GetFormat(Type formatType)
+ public object GetFormat(Type formatType)
{
return (formatType == typeof(DateTimeFormatInfo) ? this : null);
}
- public Object Clone()
+ public object Clone()
{
DateTimeFormatInfo n = (DateTimeFormatInfo)MemberwiseClone();
// We can use the data member calendar in the setter, instead of the property Calendar,
@@ -403,7 +403,7 @@ namespace System.Globalization
}
- public String AMDesignator
+ public string AMDesignator
{
get
{
@@ -546,7 +546,7 @@ namespace System.Globalization
============================================================================*/
- public int GetEra(String eraName)
+ public int GetEra(string eraName)
{
if (eraName == null)
{
@@ -602,7 +602,7 @@ namespace System.Globalization
}
- internal String[] EraNames
+ internal string[] EraNames
{
get
{
@@ -624,7 +624,7 @@ namespace System.Globalization
============================================================================*/
// Era names are 1 indexed
- public String GetEraName(int era)
+ public string GetEraName(int era)
{
if (era == Calendar.CurrentEra)
{
@@ -641,7 +641,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
- internal String[] AbbreviatedEraNames
+ internal string[] AbbreviatedEraNames
{
get
{
@@ -654,7 +654,7 @@ namespace System.Globalization
}
// Era names are 1 indexed
- public String GetAbbreviatedEraName(int era)
+ public string GetAbbreviatedEraName(int era)
{
if (AbbreviatedEraNames.Length == 0)
{
@@ -673,7 +673,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
- internal String[] AbbreviatedEnglishEraNames
+ internal string[] AbbreviatedEnglishEraNames
{
get
{
@@ -772,7 +772,7 @@ namespace System.Globalization
}
}
- public String FullDateTimePattern
+ public string FullDateTimePattern
{
get
{
@@ -802,7 +802,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String LongDatePattern
+ public string LongDatePattern
{
get
{
@@ -842,7 +842,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String LongTimePattern
+ public string LongTimePattern
{
get
{
@@ -881,7 +881,7 @@ namespace System.Globalization
// Note: just to be confusing there's only 1 month day pattern, not a whole list
- public String MonthDayPattern
+ public string MonthDayPattern
{
get
{
@@ -909,7 +909,7 @@ namespace System.Globalization
}
- public String PMDesignator
+ public string PMDesignator
{
get
{
@@ -937,7 +937,7 @@ namespace System.Globalization
}
- public String RFC1123Pattern
+ public string RFC1123Pattern
{
get
{
@@ -950,7 +950,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String ShortDatePattern
+ public string ShortDatePattern
{
get
{
@@ -991,7 +991,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String ShortTimePattern
+ public string ShortTimePattern
{
get
{
@@ -1026,7 +1026,7 @@ namespace System.Globalization
}
- public String SortableDateTimePattern
+ public string SortableDateTimePattern
{
get
{
@@ -1041,7 +1041,7 @@ namespace System.Globalization
** concatation every time somebody asks for the general format.
==============================================================================*/
- internal String GeneralShortTimePattern
+ internal string GeneralShortTimePattern
{
get
{
@@ -1060,7 +1060,7 @@ namespace System.Globalization
** concatation every time somebody asks for the general format.
==============================================================================*/
- internal String GeneralLongTimePattern
+ internal string GeneralLongTimePattern
{
get
{
@@ -1079,7 +1079,7 @@ namespace System.Globalization
** concatation every time somebody uses this form
==============================================================================*/
- internal String DateTimeOffsetPattern
+ internal string DateTimeOffsetPattern
{
get
{
@@ -1168,7 +1168,7 @@ namespace System.Globalization
}
}
- public String UniversalSortableDateTimePattern
+ public string UniversalSortableDateTimePattern
{
get
{
@@ -1181,7 +1181,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String YearMonthPattern
+ public string YearMonthPattern
{
get
{
@@ -1215,7 +1215,7 @@ namespace System.Globalization
//
// Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value"
//
- private static void CheckNullValue(String[] values, int length)
+ private static void CheckNullValue(string[] values, int length)
{
Debug.Assert(values != null, "value != null");
Debug.Assert(values.Length >= length);
@@ -1230,11 +1230,11 @@ namespace System.Globalization
}
- public String[] AbbreviatedDayNames
+ public string[] AbbreviatedDayNames
{
get
{
- return ((String[])internalGetAbbreviatedDayOfWeekNames().Clone());
+ return ((string[])internalGetAbbreviatedDayOfWeekNames().Clone());
}
set
@@ -1258,11 +1258,11 @@ namespace System.Globalization
}
// Returns the string array of the one-letter day of week names.
- public String[] ShortestDayNames
+ public string[] ShortestDayNames
{
get
{
- return ((String[])internalGetSuperShortDayNames().Clone());
+ return ((string[])internalGetSuperShortDayNames().Clone());
}
set
@@ -1284,11 +1284,11 @@ namespace System.Globalization
}
- public String[] DayNames
+ public string[] DayNames
{
get
{
- return ((String[])internalGetDayOfWeekNames().Clone());
+ return ((string[])internalGetDayOfWeekNames().Clone());
}
set
@@ -1312,11 +1312,11 @@ namespace System.Globalization
}
- public String[] AbbreviatedMonthNames
+ public string[] AbbreviatedMonthNames
{
get
{
- return ((String[])internalGetAbbreviatedMonthNames().Clone());
+ return ((string[])internalGetAbbreviatedMonthNames().Clone());
}
set
@@ -1339,11 +1339,11 @@ namespace System.Globalization
}
- public String[] MonthNames
+ public string[] MonthNames
{
get
{
- return ((String[])internalGetMonthNames().Clone());
+ return ((string[])internalGetMonthNames().Clone());
}
set
@@ -1398,13 +1398,13 @@ namespace System.Globalization
// Exceptions:
// ArgumentOutOfRangeException When month name is invalid.
//
- internal String internalGetMonthName(int month, MonthNameStyles style, bool abbreviated)
+ internal string internalGetMonthName(int month, MonthNameStyles style, bool abbreviated)
{
//
// Right now, style is mutual exclusive, but I make the style to be flag so that
// maybe we can combine flag if there is such a need.
//
- String[] monthNamesArray = null;
+ string[] monthNamesArray = null;
switch (style)
{
case MonthNameStyles.Genitive:
@@ -1436,7 +1436,7 @@ namespace System.Globalization
// Arguments:
// abbreviated When true, return abbreviated form. Otherwise, return a full form.
//
- private String[] internalGetGenitiveMonthNames(bool abbreviated)
+ private string[] internalGetGenitiveMonthNames(bool abbreviated)
{
if (abbreviated)
{
@@ -1465,7 +1465,7 @@ namespace System.Globalization
// If this culture does not have different month names in a leap year, the normal month name is returned.
// Arguments: None. (can use abbreviated later if needed)
//
- internal String[] internalGetLeapYearMonthNames(/*bool abbreviated*/)
+ internal string[] internalGetLeapYearMonthNames(/*bool abbreviated*/)
{
if (this.leapYearMonthNames == null)
{
@@ -1478,7 +1478,7 @@ namespace System.Globalization
}
- public String GetAbbreviatedDayName(DayOfWeek dayofweek)
+ public string GetAbbreviatedDayName(DayOfWeek dayofweek)
{
if ((int)dayofweek < 0 || (int)dayofweek > 6)
{
@@ -1510,13 +1510,13 @@ namespace System.Globalization
}
// Get all possible combination of inputs
- private static String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString)
+ private static string[] GetCombinedPatterns(string[] patterns1, string[] patterns2, string connectString)
{
Debug.Assert(patterns1 != null);
Debug.Assert(patterns2 != null);
// Get array size
- String[] result = new String[patterns1.Length * patterns2.Length];
+ string[] result = new string[patterns1.Length * patterns2.Length];
// Counter of actual results
int k = 0;
@@ -1535,11 +1535,11 @@ namespace System.Globalization
public string[] GetAllDateTimePatterns()
{
- List<String> results = new List<String>(DEFAULT_ALL_DATETIMES_SIZE);
+ List<string> results = new List<string>(DEFAULT_ALL_DATETIMES_SIZE);
for (int i = 0; i < DateTimeFormat.allStandardFormats.Length; i++)
{
- String[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]);
+ string[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]);
for (int j = 0; j < strings.Length; j++)
{
results.Add(strings[j]);
@@ -1550,7 +1550,7 @@ namespace System.Globalization
public string[] GetAllDateTimePatterns(char format)
{
- String[] result = null;
+ string[] result = null;
switch (format)
{
@@ -1575,18 +1575,18 @@ namespace System.Globalization
break;
case 'm':
case 'M':
- result = new String[] { MonthDayPattern };
+ result = new string[] { MonthDayPattern };
break;
case 'o':
case 'O':
- result = new String[] { RoundtripFormat };
+ result = new string[] { RoundtripFormat };
break;
case 'r':
case 'R':
- result = new String[] { rfc1123Pattern };
+ result = new string[] { rfc1123Pattern };
break;
case 's':
- result = new String[] { sortableDateTimePattern };
+ result = new string[] { sortableDateTimePattern };
break;
case 't':
result = this.AllShortTimePatterns;
@@ -1595,20 +1595,20 @@ namespace System.Globalization
result = this.AllLongTimePatterns;
break;
case 'u':
- result = new String[] { UniversalSortableDateTimePattern };
+ result = new string[] { UniversalSortableDateTimePattern };
break;
case 'y':
case 'Y':
result = this.AllYearMonthPatterns;
break;
default:
- throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format));
+ throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format));
}
return (result);
}
- public String GetDayName(DayOfWeek dayofweek)
+ public string GetDayName(DayOfWeek dayofweek)
{
if ((int)dayofweek < 0 || (int)dayofweek > 6)
{
@@ -1621,7 +1621,7 @@ namespace System.Globalization
return (internalGetDayOfWeekNames()[(int)dayofweek]);
}
- public String GetAbbreviatedMonthName(int month)
+ public string GetAbbreviatedMonthName(int month)
{
if (month < 1 || month > 13)
{
@@ -1633,7 +1633,7 @@ namespace System.Globalization
return (internalGetAbbreviatedMonthNames()[month - 1]);
}
- public String GetMonthName(int month)
+ public string GetMonthName(int month)
{
if (month < 1 || month > 13)
{
@@ -1690,7 +1690,7 @@ namespace System.Globalization
else
{
// Not found, make room for it
- newPatterns = new String[patterns.Length + 1];
+ newPatterns = new string[patterns.Length + 1];
// Copy existing array
Array.Copy(patterns, 0, newPatterns, 1, patterns.Length);
@@ -1704,12 +1704,12 @@ namespace System.Globalization
}
// Needed by DateTimeFormatInfo and DateTimeFormat
- internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
- internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
+ internal const string RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+ internal const string RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
// Default string isn't necessarily in our string array, so get the
// merged patterns of both
- private String[] AllYearMonthPatterns
+ private string[] AllYearMonthPatterns
{
get
{
@@ -1717,7 +1717,7 @@ namespace System.Globalization
}
}
- private String[] AllShortDatePatterns
+ private string[] AllShortDatePatterns
{
get
{
@@ -1725,7 +1725,7 @@ namespace System.Globalization
}
}
- private String[] AllShortTimePatterns
+ private string[] AllShortTimePatterns
{
get
{
@@ -1733,7 +1733,7 @@ namespace System.Globalization
}
}
- private String[] AllLongDatePatterns
+ private string[] AllLongDatePatterns
{
get
{
@@ -1741,7 +1741,7 @@ namespace System.Globalization
}
}
- private String[] AllLongTimePatterns
+ private string[] AllLongTimePatterns
{
get
{
@@ -1751,7 +1751,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllYearMonthPatterns
- private String[] UnclonedYearMonthPatterns
+ private string[] UnclonedYearMonthPatterns
{
get
{
@@ -1770,7 +1770,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllShortDatePatterns
- private String[] UnclonedShortDatePatterns
+ private string[] UnclonedShortDatePatterns
{
get
{
@@ -1788,7 +1788,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllLongDatePatterns
- private String[] UnclonedLongDatePatterns
+ private string[] UnclonedLongDatePatterns
{
get
{
@@ -1806,7 +1806,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllShortTimePatterns
- private String[] UnclonedShortTimePatterns
+ private string[] UnclonedShortTimePatterns
{
get
{
@@ -1823,7 +1823,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllLongTimePatterns
- private String[] UnclonedLongTimePatterns
+ private string[] UnclonedLongTimePatterns
{
get
{
@@ -1896,7 +1896,7 @@ namespace System.Globalization
//
// WARNING: If more validation is ever done in one place, it should be done in the other.
//
- public void SetAllDateTimePatterns(String[] patterns, char format)
+ public void SetAllDateTimePatterns(string[] patterns, char format)
{
if (IsReadOnly)
throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
@@ -1950,18 +1950,18 @@ namespace System.Globalization
break;
default:
- throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format));
+ throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format));
}
// Clear the token hash table, note that even short dates could require this
ClearTokenHashTable();
}
- public String[] AbbreviatedMonthGenitiveNames
+ public string[] AbbreviatedMonthGenitiveNames
{
get
{
- return ((String[])internalGetGenitiveMonthNames(true).Clone());
+ return ((string[])internalGetGenitiveMonthNames(true).Clone());
}
set
@@ -1983,11 +1983,11 @@ namespace System.Globalization
}
}
- public String[] MonthGenitiveNames
+ public string[] MonthGenitiveNames
{
get
{
- return ((String[])internalGetGenitiveMonthNames(false).Clone());
+ return ((string[])internalGetGenitiveMonthNames(false).Clone());
}
set
@@ -2010,23 +2010,35 @@ namespace System.Globalization
}
//
+ // Decimal separator used by positive TimeSpan pattern
+ //
+ private string _decimalSeparator;
+ internal string DecimalSeparator
+ {
+ get
+ {
+ if (_decimalSeparator == null)
+ {
+ CultureData cultureDataWithoutUserOverrides = _cultureData.UseUserOverride ?
+ CultureData.GetCultureData(_cultureData.CultureName, false) :
+ _cultureData;
+ _decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator;
+ }
+ return _decimalSeparator;
+ }
+ }
+
+ //
// Positive TimeSpan Pattern
//
private string _fullTimeSpanPositivePattern;
- internal String FullTimeSpanPositivePattern
+ internal string FullTimeSpanPositivePattern
{
get
{
if (_fullTimeSpanPositivePattern == null)
{
- CultureData cultureDataWithoutUserOverrides;
- if (_cultureData.UseUserOverride)
- cultureDataWithoutUserOverrides = CultureData.GetCultureData(_cultureData.CultureName, false);
- else
- cultureDataWithoutUserOverrides = _cultureData;
- String decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator;
-
- _fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + decimalSeparator + "'FFFFFFF";
+ _fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + DecimalSeparator + "'FFFFFFF";
}
return _fullTimeSpanPositivePattern;
}
@@ -2036,7 +2048,7 @@ namespace System.Globalization
// Negative TimeSpan Pattern
//
private string _fullTimeSpanNegativePattern;
- internal String FullTimeSpanNegativePattern
+ internal string FullTimeSpanNegativePattern
{
get
{
@@ -2070,7 +2082,7 @@ namespace System.Globalization
| DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal
| DateTimeStyles.AssumeUniversal | DateTimeStyles.RoundtripKind);
- internal static void ValidateStyles(DateTimeStyles style, String parameterName)
+ internal static void ValidateStyles(DateTimeStyles style, string parameterName)
{
if ((style & InvalidDateTimeStyles) != 0)
{
@@ -2106,7 +2118,7 @@ namespace System.Globalization
return formatFlags;
}
- internal Boolean HasForceTwoDigitYears
+ internal bool HasForceTwoDigitYears
{
get
{
@@ -2129,7 +2141,7 @@ namespace System.Globalization
}
// Returns whether the YearMonthAdjustment function has any fix-up work to do for this culture/calendar.
- internal Boolean HasYearMonthAdjustment
+ internal bool HasYearMonthAdjustment
{
get
{
@@ -2142,7 +2154,7 @@ namespace System.Globalization
// the Hebrew calendar, but this could be extended to other cultures.
//
// The return value is whether the year and month are actually valid for this calendar.
- internal Boolean YearMonthAdjustment(ref int year, ref int month, Boolean parsedMonthName)
+ internal bool YearMonthAdjustment(ref int year, ref int month, bool parsedMonthName)
{
if ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0)
{
@@ -2189,45 +2201,45 @@ namespace System.Globalization
private const int TOKEN_HASH_SIZE = 199;
private const int SECOND_PRIME = 197;
- private const String dateSeparatorOrTimeZoneOffset = "-";
- private const String invariantDateSeparator = "/";
- private const String invariantTimeSeparator = ":";
+ private const string dateSeparatorOrTimeZoneOffset = "-";
+ private const string invariantDateSeparator = "/";
+ private const string invariantTimeSeparator = ":";
//
// Common Ignorable Symbols
//
- internal const String IgnorablePeriod = ".";
- internal const String IgnorableComma = ",";
+ internal const string IgnorablePeriod = ".";
+ internal const string IgnorableComma = ",";
//
// Year/Month/Day suffixes
//
- internal const String CJKYearSuff = "\u5e74";
- internal const String CJKMonthSuff = "\u6708";
- internal const String CJKDaySuff = "\u65e5";
+ internal const string CJKYearSuff = "\u5e74";
+ internal const string CJKMonthSuff = "\u6708";
+ internal const string CJKDaySuff = "\u65e5";
- internal const String KoreanYearSuff = "\ub144";
- internal const String KoreanMonthSuff = "\uc6d4";
- internal const String KoreanDaySuff = "\uc77c";
+ internal const string KoreanYearSuff = "\ub144";
+ internal const string KoreanMonthSuff = "\uc6d4";
+ internal const string KoreanDaySuff = "\uc77c";
- internal const String KoreanHourSuff = "\uc2dc";
- internal const String KoreanMinuteSuff = "\ubd84";
- internal const String KoreanSecondSuff = "\ucd08";
+ internal const string KoreanHourSuff = "\uc2dc";
+ internal const string KoreanMinuteSuff = "\ubd84";
+ internal const string KoreanSecondSuff = "\ucd08";
- internal const String CJKHourSuff = "\u6642";
- internal const String ChineseHourSuff = "\u65f6";
+ internal const string CJKHourSuff = "\u6642";
+ internal const string ChineseHourSuff = "\u65f6";
- internal const String CJKMinuteSuff = "\u5206";
- internal const String CJKSecondSuff = "\u79d2";
+ internal const string CJKMinuteSuff = "\u5206";
+ internal const string CJKSecondSuff = "\u79d2";
- internal const String LocalTimeMark = "T";
+ internal const string LocalTimeMark = "T";
- internal const String GMTName = "GMT";
- internal const String ZuluName = "Z";
+ internal const string GMTName = "GMT";
+ internal const string ZuluName = "Z";
- internal const String KoreanLangName = "ko";
- internal const String JapaneseLangName = "ja";
- internal const String EnglishLangName = "en";
+ internal const string KoreanLangName = "ko";
+ internal const string JapaneseLangName = "ja";
+ internal const string EnglishLangName = "en";
private static volatile DateTimeFormatInfo s_jajpDTFI;
private static volatile DateTimeFormatInfo s_zhtwDTFI;
@@ -2341,7 +2353,7 @@ namespace System.Globalization
InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0);
}
- String[] dateWords = null;
+ string[] dateWords = null;
DateTimeFormatInfoScanner scanner = null;
// We need to rescan the date words since we're always synthetic
@@ -2355,7 +2367,7 @@ namespace System.Globalization
// This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol.
bool useDateSepAsIgnorableSymbol = false;
- String monthPostfix = null;
+ string monthPostfix = null;
if (dateWords != null)
{
// There are DateWords. It could be a real date word (such as "de"), or a monthPostfix.
@@ -2372,7 +2384,7 @@ namespace System.Globalization
AddMonthNames(temp, monthPostfix);
break;
case DateTimeFormatInfoScanner.IgnorableSymbolChar:
- String symbol = dateWords[i].Substring(1);
+ string symbol = dateWords[i].Substring(1);
InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0);
if (this.DateSeparator.Trim(null).Equals(symbol))
{
@@ -2412,7 +2424,7 @@ namespace System.Globalization
{
for (int i = 1; i <= 13; i++)
{
- String str;
+ string str;
str = internalGetMonthName(i, MonthNameStyles.Genitive, false);
InsertHash(temp, str, TokenType.MonthToken, i);
}
@@ -2422,7 +2434,7 @@ namespace System.Globalization
{
for (int i = 1; i <= 13; i++)
{
- String str;
+ string str;
str = internalGetMonthName(i, MonthNameStyles.LeapYear, false);
InsertHash(temp, str, TokenType.MonthToken, i);
}
@@ -2432,7 +2444,7 @@ namespace System.Globalization
{
//String str = GetDayOfWeekNames()[i];
// We have to call public methods here to work with inherited DTFI.
- String str = GetDayName((DayOfWeek)i);
+ string str = GetDayName((DayOfWeek)i);
InsertHash(temp, str, TokenType.DayOfWeekToken, i);
str = GetAbbreviatedDayName((DayOfWeek)i);
@@ -2452,7 +2464,7 @@ namespace System.Globalization
// Japanese allows day of week forms like: "(Tue)"
for (int i = 0; i < 7; i++)
{
- String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
+ string specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i);
}
if (this.Calendar.GetType() != typeof(JapaneseCalendar))
@@ -2488,7 +2500,7 @@ namespace System.Globalization
// Add invariant month names and day names.
for (int i = 1; i <= 12; i++)
{
- String str;
+ string str;
// We have to call public methods here to work with inherited DTFI.
// Insert the month name first, so that they are at the front of abbreviated
// month names.
@@ -2501,7 +2513,7 @@ namespace System.Globalization
for (int i = 0; i < 7; i++)
{
// We have to call public methods here to work with inherited DTFI.
- String str = InvariantInfo.GetDayName((DayOfWeek)i);
+ string str = InvariantInfo.GetDayName((DayOfWeek)i);
InsertHash(temp, str, TokenType.DayOfWeekToken, i);
str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i);
@@ -2526,11 +2538,11 @@ namespace System.Globalization
return (temp);
}
- private void AddMonthNames(TokenHashValue[] temp, String monthPostfix)
+ private void AddMonthNames(TokenHashValue[] temp, string monthPostfix)
{
for (int i = 1; i <= 13; i++)
{
- String str;
+ string str;
//str = internalGetMonthName(i, MonthNameStyles.Regular, false);
// We have to call public methods here to work with inherited DTFI.
// Insert the month name first, so that they are at the front of abbreviated
@@ -2568,7 +2580,7 @@ namespace System.Globalization
private static bool TryParseHebrewNumber(
ref __DTString str,
- out Boolean badFormat,
+ out bool badFormat,
out int number)
{
number = -1;
@@ -2631,7 +2643,7 @@ namespace System.Globalization
Debug.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length");
char ch = str.m_current;
- bool isLetter = Char.IsLetter(ch);
+ bool isLetter = char.IsLetter(ch);
if (isLetter)
{
ch = this.Culture.TextInfo.ToLower(ch);
@@ -2689,7 +2701,7 @@ namespace System.Globalization
{
// Check word boundary. The next character should NOT be a letter.
char nextCh = str.Value[nextCharIndex];
- compareStrings = !(Char.IsLetter(nextCh));
+ compareStrings = !(char.IsLetter(nextCh));
}
}
@@ -2724,7 +2736,7 @@ namespace System.Globalization
return (false);
}
- private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, String str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe)
+ private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, string str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe)
{
// Remember the current slot.
TokenHashValue previousNode = hashTable[hashcode];
@@ -2757,7 +2769,7 @@ namespace System.Globalization
Debug.Fail("The hashtable is full. This should not happen.");
}
- private void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue)
+ private void InsertHash(TokenHashValue[] hashTable, string str, TokenType tokenType, int tokenValue)
{
// The month of the 13th month is allowed to be null, so make sure that we ignore null value here.
if (str == null || str.Length == 0)
@@ -2768,7 +2780,7 @@ namespace System.Globalization
int i = 0;
// If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by
// DateTime.Parse().
- if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1]))
+ if (char.IsWhiteSpace(str[0]) || char.IsWhiteSpace(str[str.Length - 1]))
{
str = str.Trim(null); // Trim white space characters.
// Could have space for separators
@@ -2860,11 +2872,11 @@ namespace System.Globalization
internal class TokenHashValue
{
- internal String tokenString;
+ internal string tokenString;
internal TokenType tokenType;
internal int tokenValue;
- internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue)
+ internal TokenHashValue(string tokenString, TokenType tokenType, int tokenValue)
{
this.tokenString = tokenString;
this.tokenType = tokenType;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
index d3c3aac84..de43c2da3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
@@ -94,23 +94,23 @@ namespace System.Globalization
internal const char IgnorableSymbolChar = '\xe001';
// Known CJK suffix
- internal const String CJKYearSuff = "\u5e74";
- internal const String CJKMonthSuff = "\u6708";
- internal const String CJKDaySuff = "\u65e5";
+ internal const string CJKYearSuff = "\u5e74";
+ internal const string CJKMonthSuff = "\u6708";
+ internal const string CJKDaySuff = "\u65e5";
- internal const String KoreanYearSuff = "\ub144";
- internal const String KoreanMonthSuff = "\uc6d4";
- internal const String KoreanDaySuff = "\uc77c";
+ internal const string KoreanYearSuff = "\ub144";
+ internal const string KoreanMonthSuff = "\uc6d4";
+ internal const string KoreanDaySuff = "\uc77c";
- internal const String KoreanHourSuff = "\uc2dc";
- internal const String KoreanMinuteSuff = "\ubd84";
- internal const String KoreanSecondSuff = "\ucd08";
+ internal const string KoreanHourSuff = "\uc2dc";
+ internal const string KoreanMinuteSuff = "\ubd84";
+ internal const string KoreanSecondSuff = "\ucd08";
- internal const String CJKHourSuff = "\u6642";
- internal const String ChineseHourSuff = "\u65f6";
+ internal const string CJKHourSuff = "\u6642";
+ internal const string ChineseHourSuff = "\u65f6";
- internal const String CJKMinuteSuff = "\u5206";
- internal const String CJKSecondSuff = "\u79d2";
+ internal const string CJKMinuteSuff = "\u5206";
+ internal const string CJKSecondSuff = "\u79d2";
// The collection fo date words & postfix.
internal List<string> m_dateWords = new List<string>();
@@ -127,23 +127,23 @@ namespace System.Globalization
// Add known words into the hash table.
// Skip these special symbols.
- temp.Add("/", String.Empty);
- temp.Add("-", String.Empty);
- temp.Add(".", String.Empty);
+ temp.Add("/", string.Empty);
+ temp.Add("-", string.Empty);
+ temp.Add(".", string.Empty);
// Skip known CJK suffixes.
- temp.Add(CJKYearSuff, String.Empty);
- temp.Add(CJKMonthSuff, String.Empty);
- temp.Add(CJKDaySuff, String.Empty);
- temp.Add(KoreanYearSuff, String.Empty);
- temp.Add(KoreanMonthSuff, String.Empty);
- temp.Add(KoreanDaySuff, String.Empty);
- temp.Add(KoreanHourSuff, String.Empty);
- temp.Add(KoreanMinuteSuff, String.Empty);
- temp.Add(KoreanSecondSuff, String.Empty);
- temp.Add(CJKHourSuff, String.Empty);
- temp.Add(ChineseHourSuff, String.Empty);
- temp.Add(CJKMinuteSuff, String.Empty);
- temp.Add(CJKSecondSuff, String.Empty);
+ temp.Add(CJKYearSuff, string.Empty);
+ temp.Add(CJKMonthSuff, string.Empty);
+ temp.Add(CJKDaySuff, string.Empty);
+ temp.Add(KoreanYearSuff, string.Empty);
+ temp.Add(KoreanMonthSuff, string.Empty);
+ temp.Add(KoreanDaySuff, string.Empty);
+ temp.Add(KoreanHourSuff, string.Empty);
+ temp.Add(KoreanMinuteSuff, string.Empty);
+ temp.Add(KoreanSecondSuff, string.Empty);
+ temp.Add(CJKHourSuff, string.Empty);
+ temp.Add(ChineseHourSuff, string.Empty);
+ temp.Add(CJKMinuteSuff, string.Empty);
+ temp.Add(CJKSecondSuff, string.Empty);
s_knownWords = temp;
}
@@ -163,7 +163,7 @@ namespace System.Globalization
// Note that the index can be pattern.Length if we reach the end of the string.
//
////////////////////////////////////////////////////////////////////////////
- internal static int SkipWhiteSpacesAndNonLetter(String pattern, int currentIndex)
+ internal static int SkipWhiteSpacesAndNonLetter(string pattern, int currentIndex)
{
while (currentIndex < pattern.Length)
{
@@ -189,7 +189,7 @@ namespace System.Globalization
break;
}
}
- if (Char.IsLetter(ch) || ch == '\'' || ch == '.')
+ if (char.IsLetter(ch) || ch == '\'' || ch == '.')
{
break;
}
@@ -211,7 +211,7 @@ namespace System.Globalization
// word: The date word or postfix to be added.
//
////////////////////////////////////////////////////////////////////////////
- internal void AddDateWordOrPostfix(String formatPostfix, String str)
+ internal void AddDateWordOrPostfix(string formatPostfix, string str)
{
if (str.Length > 0)
{
@@ -221,7 +221,7 @@ namespace System.Globalization
AddIgnorableSymbols(".");
return;
}
- String words;
+ string words;
if (KnownWords.TryGetValue(str, out words) == false)
{
if (m_dateWords == null)
@@ -231,7 +231,7 @@ namespace System.Globalization
if (formatPostfix == "MMMM")
{
// Add the word into the ArrayList as "\xfffe" + real month postfix.
- String temp = MonthPostfixChar + str;
+ string temp = MonthPostfixChar + str;
if (!m_dateWords.Contains(temp))
{
m_dateWords.Add(temp);
@@ -246,7 +246,7 @@ namespace System.Globalization
if (str[str.Length - 1] == '.')
{
// Old version ignore the trialing dot in the date words. Support this as well.
- String strWithoutDot = str.Substring(0, str.Length - 1);
+ string strWithoutDot = str.Substring(0, str.Length - 1);
if (!m_dateWords.Contains(strWithoutDot))
{
m_dateWords.Add(strWithoutDot);
@@ -272,7 +272,7 @@ namespace System.Globalization
//
//
////////////////////////////////////////////////////////////////////////////
- internal int AddDateWords(String pattern, int index, String formatPostfix)
+ internal int AddDateWords(string pattern, int index, string formatPostfix)
{
// Skip any whitespaces so we will start from a letter.
int newIndex = SkipWhiteSpacesAndNonLetter(pattern, index);
@@ -314,7 +314,7 @@ namespace System.Globalization
index++;
}
}
- else if (Char.IsWhiteSpace(ch))
+ else if (char.IsWhiteSpace(ch))
{
// Found a whitespace. We have to add the current date word/postfix.
AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
@@ -341,7 +341,7 @@ namespace System.Globalization
// A simple helper to find the repeat count for a specified char.
//
////////////////////////////////////////////////////////////////////////////
- internal static int ScanRepeatChar(String pattern, char ch, int index, out int count)
+ internal static int ScanRepeatChar(string pattern, char ch, int index, out int count)
{
count = 1;
while (++index < pattern.Length && pattern[index] == ch)
@@ -367,7 +367,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- internal void AddIgnorableSymbols(String text)
+ internal void AddIgnorableSymbols(string text)
{
if (m_dateWords == null)
{
@@ -375,7 +375,7 @@ namespace System.Globalization
m_dateWords = new List<string>();
}
// Add the ignorable symbol into the ArrayList.
- String temp = IgnorableSymbolChar + text;
+ string temp = IgnorableSymbolChar + text;
if (!m_dateWords.Contains(temp))
{
m_dateWords.Add(temp);
@@ -421,7 +421,7 @@ namespace System.Globalization
// Windows style pattern uses '' for single quote, while .NET uses \'
//
////////////////////////////////////////////////////////////////////////////
- internal void ScanDateWord(String pattern)
+ internal void ScanDateWord(string pattern)
{
// Check if we have found all of the year/month/day pattern.
_ymdFlags = FoundDatePattern.None;
@@ -479,7 +479,7 @@ namespace System.Globalization
i++;
break;
default:
- if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch))
+ if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !char.IsWhiteSpace(ch))
{
// We are not seeing "." after YMD. Clear the flag.
_ymdFlags = FoundDatePattern.None;
@@ -497,10 +497,10 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- internal String[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi)
+ internal string[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi)
{
// Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix.
- String[] datePatterns = dtfi.GetAllDateTimePatterns('D');
+ string[] datePatterns = dtfi.GetAllDateTimePatterns('D');
int i;
// Scan the long date patterns
@@ -539,10 +539,10 @@ namespace System.Globalization
ScanDateWord(datePatterns[i]);
}
- String[] result = null;
+ string[] result = null;
if (m_dateWords != null && m_dateWords.Count > 0)
{
- result = new String[m_dateWords.Count];
+ result = new string[m_dateWords.Count];
for (i = 0; i < m_dateWords.Count; i++)
{
result[i] = m_dateWords[i];
@@ -558,7 +558,7 @@ namespace System.Globalization
// the format flag.
//
////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagGenitiveMonth(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ internal static FORMATFLAGS GetFormatFlagGenitiveMonth(string[] monthNames, string[] genitveMonthNames, string[] abbrevMonthNames, string[] genetiveAbbrevMonthNames)
{
// If we have different names in regular and genitive month names, use genitive month flag.
return ((!EqualStringArrays(monthNames, genitveMonthNames) || !EqualStringArrays(abbrevMonthNames, genetiveAbbrevMonthNames))
@@ -570,7 +570,7 @@ namespace System.Globalization
// Scan the month names to see if spaces are used or start with a digit, and return the format flag
//
////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(string[] monthNames, string[] genitveMonthNames, string[] abbrevMonthNames, string[] genetiveAbbrevMonthNames)
{
FORMATFLAGS formatFlags = 0;
formatFlags |= (ArrayElementsBeginWithDigit(monthNames) ||
@@ -592,7 +592,7 @@ namespace System.Globalization
// Scan the day names and set the correct format flag.
//
////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(String[] dayNames, String[] abbrevDayNames)
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(string[] dayNames, string[] abbrevDayNames)
{
return ((ArrayElementsHaveSpace(dayNames) ||
ArrayElementsHaveSpace(abbrevDayNames))
@@ -659,7 +659,7 @@ namespace System.Globalization
// so we don't have to go to native code side.
for (int j = 0; j < array[i].Length; j++)
{
- if (Char.IsWhiteSpace(array[i][j]))
+ if (char.IsWhiteSpace(array[i][j]))
{
return true;
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
index 5b285eb5d..8d703ea98 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
@@ -11,7 +11,7 @@ namespace System
{
internal static class DateTimeParse
{
- internal const Int32 MaxDateTimeNumberDigits = 8;
+ internal const int MaxDateTimeNumberDigits = 8;
internal delegate bool MatchNumberDelegate(ref __DTString str, int digitLen, out int result);
@@ -96,7 +96,7 @@ namespace System
return DoStrictParse(s, format, style, dtfi, ref result);
}
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
@@ -112,7 +112,7 @@ namespace System
}
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
@@ -130,7 +130,7 @@ namespace System
}
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
{
result = DateTime.MinValue;
@@ -148,7 +148,7 @@ namespace System
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
{
result = DateTime.MinValue;
@@ -162,7 +162,7 @@ namespace System
return false;
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
{
if (formats == null)
@@ -331,7 +331,7 @@ namespace System
//
////////////////////////////////////////////////////////////////////////////
- // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
+ // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
private static DS[][] dateParsingStates = {
// DS.BEGIN // DS.BEGIN
new DS[] { DS.BEGIN, DS.ERROR, DS.TX_N, DS.N, DS.D_Nd, DS.T_Nt, DS.ERROR, DS.D_M, DS.D_M, DS.D_S, DS.T_S, DS.BEGIN, DS.D_Y, DS.D_Y, DS.ERROR, DS.BEGIN, DS.BEGIN, DS.ERROR},
@@ -395,13 +395,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
};
// End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCMark
- internal const String GMTName = "GMT";
- internal const String ZuluName = "Z";
+ internal const string GMTName = "GMT";
+ internal const string ZuluName = "Z";
//
// Search from the index of str at str.Index to see if the target string exists in the str.
//
- private static bool MatchWord(ref __DTString str, String target)
+ private static bool MatchWord(ref __DTString str, string target)
{
if (target.Length > (str.Value.Length - str.Index))
{
@@ -418,7 +418,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (nextCharIndex < str.Value.Length)
{
char nextCh = str.Value[nextCharIndex];
- if (Char.IsLetter(nextCh))
+ if (char.IsLetter(nextCh))
{
return (false);
}
@@ -573,7 +573,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
char nextCh = str.Value[str.Index];
// Skip whitespace, but don't update the index unless we find a time zone marker
int whitespaceCount = 0;
- while (Char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
+ while (char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
{
whitespaceCount++;
nextCh = str.Value[str.Index + whitespaceCount];
@@ -602,7 +602,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// This is the lexer. Check the character at the current index, and put the found token in dtok and
// some raw date/time information in raw.
//
- private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
+ private static bool Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
{
TokenType tokenType;
int tokenValue;
@@ -713,7 +713,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
+ // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
// we are sure we are not parsing time.
dtok.dtt = DTT.YearDateSep;
break;
@@ -1002,7 +1002,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
+ // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
// we are sure we are not parsing time.
dtok.dtt = DTT.MonthDatesep;
break;
@@ -1119,7 +1119,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
break;
case TokenType.UnknownToken:
- if (Char.IsLetter(str.m_current))
+ if (char.IsLetter(str.m_current))
{
result.SetFailure(ParseFailureKind.FormatWithOriginalDateTimeAndParameter, nameof(SR.Format_UnknownDateTimeWord), str.Index);
LexTraceExit("0200", dps);
@@ -1128,7 +1128,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0))
{
- Int32 originalIndex = str.Index;
+ int originalIndex = str.Index;
if (ParseTimeZone(ref str, ref result.timeZoneOffset))
{
result.flags |= ParseFlags.TimeZoneUsed;
@@ -1160,10 +1160,10 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean VerifyValidPunctuation(ref __DTString str)
+ private static bool VerifyValidPunctuation(ref __DTString str)
{
// Compatability Behavior. Allow trailing nulls and surrounding hashes
- Char ch = str.Value[str.Index];
+ char ch = str.Value[str.Index];
if (ch == '#')
{
bool foundStart = false;
@@ -1198,7 +1198,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
}
- else if ((!Char.IsWhiteSpace(ch)))
+ else if ((!char.IsWhiteSpace(ch)))
{
// Anything other than whitespace outside hashes is invalid
if (!foundStart || foundEnd)
@@ -1212,7 +1212,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// The has was un-paired
return false;
}
- // Valid Hash usage: eat the hash and continue.
+ // Valid Hash usage: eat the hash and continue.
str.GetNext();
return true;
}
@@ -1247,7 +1247,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for YMD, 1 for MDY, 2 for DMY, otherwise -1.
//
- private static Boolean GetYearMonthDayOrder(String datePattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetYearMonthDayOrder(string datePattern, DateTimeFormatInfo dtfi, out int order)
{
int yearOrder = -1;
int monthOrder = -1;
@@ -1345,7 +1345,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for YM, 1 for MY, otherwise -1.
//
- private static Boolean GetYearMonthOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetYearMonthOrder(string pattern, DateTimeFormatInfo dtfi, out int order)
{
int yearOrder = -1;
int monthOrder = -1;
@@ -1411,7 +1411,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for MD, 1 for DM, otherwise -1.
//
- private static Boolean GetMonthDayOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetMonthDayOrder(string pattern, DateTimeFormatInfo dtfi, out int order)
{
int monthOrder = -1;
int dayOrder = -1;
@@ -1539,7 +1539,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Processing teriminal case: DS.DX_NN
- private static Boolean GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1582,7 +1582,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Processing teriminal case: DS.DX_NNN
- private static Boolean GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1639,7 +1639,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1701,7 +1701,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
////////////////////////////////////////////////////////////////////////
- private static Boolean GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
int monthDayOrder;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder))
@@ -1722,7 +1722,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1778,7 +1778,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1848,7 +1848,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1859,7 +1859,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int n1 = raw.GetNumber(0);
int n2 = raw.GetNumber(1);
- String pattern = dtfi.ShortDatePattern;
+ string pattern = dtfi.ShortDatePattern;
// For compatibility, don't throw if we can't determine the order, but default to YMD instead
int order;
@@ -1883,7 +1883,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1923,7 +1923,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
- private static Boolean GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1941,7 +1941,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1959,7 +1959,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -2004,7 +2004,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Adjust hour according to the time mark.
//
- private static Boolean AdjustHour(ref int hour, TM timeMark)
+ private static bool AdjustHour(ref int hour, TM timeMark)
{
if (timeMark != TM.NotSet)
{
@@ -2031,7 +2031,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
@@ -2052,7 +2052,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
Debug.Assert(raw.numCount >= 2, "raw.numCount >= 2");
if ((result.flags & ParseFlags.HaveTime) != 0)
@@ -2068,7 +2068,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
@@ -2087,7 +2087,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Processing terminal state: A Date suffix followed by one number.
//
- private static Boolean GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if (raw.numCount != 1 || result.Day != -1)
{
@@ -2098,7 +2098,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if (result.Month == -1)
{
@@ -2122,7 +2122,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
// For partial CJK Dates, the only valid formats are with a specified year, followed by two numbers, which
// will be the Month and Day, and with a specified Month, when the numbers are either the year and day or
@@ -2236,7 +2236,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
////////////////////////////////////////////////////////////////////////
- internal static Boolean ProcessHebrewTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static bool ProcessHebrewTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
// The following are accepted terminal state for Hebrew date.
switch (dps)
@@ -2346,7 +2346,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// A terminal state has been reached, call the appropriate function to fill in the parsing result.
// Return true if the state is a terminal state.
//
- internal static Boolean ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static bool ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
bool passed = true;
switch (dps)
@@ -2516,7 +2516,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
DateTimeRawInfo raw = new DateTimeRawInfo(); // The buffer to store temporary parsing information.
unsafe
{
- Int32* numberPointer = stackalloc Int32[3];
+ int* numberPointer = stackalloc int[3];
raw.Init(numberPointer);
}
raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal);
@@ -2591,7 +2591,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep)
{
- // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
+ // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
// as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead
if (dps == DS.T_Nt)
{
@@ -2608,7 +2608,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
switch (dtok.dtt)
{
- // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
+ // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
// changing the token to end with space instead of Date Separator will avoid failing the parsing.
case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break;
@@ -2719,7 +2719,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
{
TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
return false;
@@ -2730,17 +2730,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Handles time zone adjustments and sets DateTimeKind values as required by the styles
- private static Boolean DetermineTimeZoneAdjustments(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles, Boolean bTimeOnly)
+ private static bool DetermineTimeZoneAdjustments(ref DateTimeResult result, DateTimeStyles styles, bool bTimeOnly)
{
if ((result.flags & ParseFlags.CaptureOffset) != 0)
{
- // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
+ // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
// no adjustment is required in most cases
- return DateTimeOffsetTimeZonePostProcessing(ref str, ref result, styles);
+ return DateTimeOffsetTimeZonePostProcessing(ref result, styles);
}
else
{
- Int64 offsetTicks = result.timeZoneOffset.Ticks;
+ long offsetTicks = result.timeZoneOffset.Ticks;
// the DateTime offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
@@ -2808,9 +2808,9 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Apply validation and adjustments specific to DateTimeOffset
- private static Boolean DateTimeOffsetTimeZonePostProcessing(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles)
+ private static bool DateTimeOffsetTimeZonePostProcessing(ref DateTimeResult result, DateTimeStyles styles)
{
- // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
+ // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
// the input string.
if ((result.flags & ParseFlags.TimeZoneUsed) == 0)
{
@@ -2826,14 +2826,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- Int64 offsetTicks = result.timeZoneOffset.Ticks;
+ long offsetTicks = result.timeZoneOffset.Ticks;
// there should be no overflow, because the offset can be no more than -+100 hours and the date already
// fits within a DateTime.
- Int64 utcTicks = result.parsedDate.Ticks - offsetTicks;
+ long utcTicks = result.parsedDate.Ticks - offsetTicks;
// For DateTimeOffset, both the parsed time and the corresponding UTC value must be within the boundaries
- // of a DateTime instance.
+ // of a DateTime instance.
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_UTCOutOfRange));
@@ -2854,7 +2854,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (((result.flags & ParseFlags.TimeZoneUsed) == 0) && ((styles & DateTimeStyles.AssumeUniversal) == 0))
{
// Handle the special case where the timeZoneOffset was defaulted to Local
- Boolean toUtcResult = AdjustTimeZoneToUniversal(ref result);
+ bool toUtcResult = AdjustTimeZoneToUniversal(ref result);
result.timeZoneOffset = TimeSpan.Zero;
return toUtcResult;
}
@@ -2875,7 +2875,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the time is 2001/06/08 14:00, and timeZoneOffset = -07:00.
// The result will be "2001/06/08 21:00"
//
- private static Boolean AdjustTimeZoneToUniversal(ref DateTimeResult result)
+ private static bool AdjustTimeZoneToUniversal(ref DateTimeResult result)
{
long resultTicks = result.parsedDate.Ticks;
resultTicks -= result.timeZoneOffset.Ticks;
@@ -2900,12 +2900,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the time is 2001/06/08 14:00, and timeZoneOffset = -05:00.
// The result will be "2001/06/08 11:00"
//
- private static Boolean AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
+ private static bool AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
{
long resultTicks = result.parsedDate.Ticks;
// Convert to local ticks
TimeZoneInfo tz = TimeZoneInfo.Local;
- Boolean isAmbiguousLocalDst = false;
+ bool isAmbiguousLocalDst = false;
if (resultTicks < Calendar.TicksPerDay)
{
//
@@ -2936,7 +2936,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
// Convert the GMT time to local time.
DateTime utcDt = new DateTime(resultTicks, DateTimeKind.Utc);
- Boolean isDaylightSavings = false;
+ bool isDaylightSavings = false;
resultTicks += TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
}
}
@@ -3061,7 +3061,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond));
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, false))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, false))
{
return false;
}
@@ -3315,7 +3315,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
for (int i = 1; i <= monthsInYear; i++)
{
- String searchStr = dtfi.GetAbbreviatedMonthName(i);
+ string searchStr = dtfi.GetAbbreviatedMonthName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInMonthNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3373,7 +3373,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
for (int i = 1; i <= monthsInYear; i++)
{
- String searchStr = dtfi.GetMonthName(i);
+ string searchStr = dtfi.GetMonthName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInMonthNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3438,7 +3438,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
{
- String searchStr = dtfi.GetAbbreviatedDayName(i);
+ string searchStr = dtfi.GetAbbreviatedDayName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInDayNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3477,7 +3477,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
{
- String searchStr = dtfi.GetDayName(i);
+ string searchStr = dtfi.GetDayName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInDayNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3517,7 +3517,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (int i = 0; i < eras.Length; i++)
{
- String searchStr = dtfi.GetEraName(eras[i]);
+ string searchStr = dtfi.GetEraName(eras[i]);
if (str.MatchSpecifiedWord(searchStr))
{
str.Index += (searchStr.Length - 1);
@@ -3560,7 +3560,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (str.GetNext())
{
- String searchStr = dtfi.AMDesignator;
+ string searchStr = dtfi.AMDesignator;
if (searchStr.Length > 0)
{
if (str.MatchSpecifiedWord(searchStr))
@@ -3668,7 +3668,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- // assume the offset is Local
+ // assume the offset is Local
return DateTime.Now;
}
@@ -3774,7 +3774,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// This method also set the dtfi according/parseInfo to some special pre-defined
// formats.
//
- private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ private static string ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
{
//
// Check the format to see if we need to override the dtfi to be InvariantInfo,
@@ -3782,24 +3782,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
switch (format[0])
{
+ case 's': // Sortable format (in local time)
case 'o':
case 'O': // Round Trip Format
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
+ ConfigureFormatOS(ref dtfi, ref parseInfo);
break;
case 'r':
case 'R': // RFC 1123 Standard. (in Universal time)
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
-
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- result.flags |= ParseFlags.Rfc1123Pattern;
- }
- break;
- case 's': // Sortable format (in local time)
- dtfi = DateTimeFormatInfo.InvariantInfo;
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
break;
case 'u': // Universal time format in sortable format.
parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
@@ -3829,9 +3819,21 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return (DateTimeFormat.GetRealFormat(format, dtfi));
}
+ private static void ConfigureFormatR(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ if ((result.flags & ParseFlags.CaptureOffset) != 0)
+ {
+ result.flags |= ParseFlags.Rfc1123Pattern;
+ }
+ }
-
-
+ private static void ConfigureFormatOS(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo)
+ {
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ }
// Given a specified format character, parse and update the parsing result.
//
@@ -4201,7 +4203,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Some cultures uses space in the quoted string. E.g. Spanish has long date format as:
// "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space
// in the quoted string.
- String quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
+ string quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
for (int i = 0; i < quotedStr.Length; i++)
{
@@ -4218,7 +4220,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot
- // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
+ // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
// fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released
// with this issue.
if ((result.flags & ParseFlags.CaptureOffset) != 0)
@@ -4443,12 +4445,32 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (formatParam.Length == 1)
{
- if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U')
+ char formatParamChar = formatParam[0];
+
+ // Fast-paths for common and important formats/configurations.
+ if (styles == DateTimeStyles.None)
+ {
+ switch (formatParamChar)
+ {
+ case 'R':
+ case 'r':
+ ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
+ return ParseFormatR(s, ref parseInfo, ref result);
+
+ case 'O':
+ case 'o':
+ ConfigureFormatOS(ref dtfi, ref parseInfo);
+ return ParseFormatO(s, ref parseInfo, ref result);
+ }
+ }
+
+ if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParamChar == 'U')
{
// The 'U' format is not allowed for DateTimeOffset
result.SetBadFormatSpecifierFailure(formatParam);
return false;
}
+
formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
}
@@ -4614,13 +4636,417 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
{
return false;
}
return true;
}
+ private static bool ParseFormatR(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ // Example:
+ // Tue, 03 Jan 2017 08:08:05 GMT
+
+ // The format is exactly 29 characters.
+ if ((uint)source.Length != 29)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the three-letter day of week. Any casing is valid.
+ DayOfWeek dayOfWeek;
+ {
+ uint dow0 = source[0], dow1 = source[1], dow2 = source[2], comma = source[3];
+
+ if ((dow0 | dow1 | dow2 | comma) > 0x7F)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma | 0x20202000;
+ switch (dowString)
+ {
+ case 0x73756E2c /* 'sun,' */: dayOfWeek = DayOfWeek.Sunday; break;
+ case 0x6d6f6e2c /* 'mon,' */: dayOfWeek = DayOfWeek.Monday; break;
+ case 0x7475652c /* 'tue,' */: dayOfWeek = DayOfWeek.Tuesday; break;
+ case 0x7765642c /* 'wed,' */: dayOfWeek = DayOfWeek.Wednesday; break;
+ case 0x7468752c /* 'thu,' */: dayOfWeek = DayOfWeek.Thursday; break;
+ case 0x6672692c /* 'fri,' */: dayOfWeek = DayOfWeek.Friday; break;
+ case 0x7361742c /* 'sat,' */: dayOfWeek = DayOfWeek.Saturday; break;
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ if (source[4] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two digit day.
+ int day;
+ {
+ uint digit1 = (uint)(source[5] - '0'), digit2 = (uint)(source[6] - '0');
+
+ if (digit1 > 9 || digit2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ day = (int)(digit1*10 + digit2);
+ }
+
+ if (source[7] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the three letter month (followed by a space). Any casing is valid.
+ int month;
+ {
+ uint m0 = source[8], m1 = source[9], m2 = source[10], space = source[11];
+
+ if ((m0 | m1 | m2 | space) > 0x7F)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ switch ((m0 << 24) | (m1 << 16) | (m2 << 8) | space | 0x20202000)
+ {
+ case 0x6a616e20 /* 'jan ' */ : month = 1; break;
+ case 0x66656220 /* 'feb ' */ : month = 2; break;
+ case 0x6d617220 /* 'mar ' */ : month = 3; break;
+ case 0x61707220 /* 'apr ' */ : month = 4; break;
+ case 0x6d617920 /* 'may ' */ : month = 5; break;
+ case 0x6a756e20 /* 'jun ' */ : month = 6; break;
+ case 0x6a756c20 /* 'jul ' */ : month = 7; break;
+ case 0x61756720 /* 'aug ' */ : month = 8; break;
+ case 0x73657020 /* 'sep ' */ : month = 9; break;
+ case 0x6f637420 /* 'oct ' */ : month = 10; break;
+ case 0x6e6f7620 /* 'nov ' */ : month = 11; break;
+ case 0x64656320 /* 'dec ' */ : month = 12; break;
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ // Parse the four-digit year.
+ int year;
+ {
+ uint y1 = (uint)(source[12] - '0'), y2 = (uint)(source[13] - '0'), y3 = (uint)(source[14] - '0'), y4 = (uint)(source[15] - '0');
+
+ if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ year = (int)(y1*1000 + y2*100 + y3*10 + y4);
+ }
+
+ if (source[16] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two digit hour.
+ int hour;
+ {
+ uint h1 = (uint)(source[17] - '0'), h2 = (uint)(source[18] - '0');
+
+ if (h1 > 9 || h2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ hour = (int)(h1*10 + h2);
+ }
+
+ if (source[19] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two-digit minute.
+ int minute;
+ {
+ uint m1 = (uint)(source[20] - '0');
+ uint m2 = (uint)(source[21] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ minute = (int)(m1*10 + m2);
+ }
+
+ if (source[22] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two-digit second.
+ int second;
+ {
+ uint s1 = (uint)(source[23] - '0'), s2 = (uint)(source[24] - '0');
+
+ if (s1 > 9 || s2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ second = (int)(s1*10 + s2);
+ }
+
+ // Parse " GMT". It must be upper case.
+ if (source[25] != ' ' || source[26] != 'G' || source[27] != 'M' || source[28] != 'T')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Validate that the parsed date is valid according to the calendar.
+ if (!parseInfo.calendar.TryToDateTime(year, month, day, hour, minute, second, 0, 0, out result.parsedDate))
+ {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
+ return false;
+ }
+
+ // And validate that the parsed day of week matches what the calendar said it should be.
+ if (dayOfWeek != result.parsedDate.DayOfWeek)
+ {
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool ParseFormatO(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ // Examples:
+ // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
+ // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
+ // 2017-06-12T05:30:45.7680000-7:00 (special-case of one-digit offset hour)
+ // 2017-06-12T05:30:45.7680000-07:00
+
+ if ((uint)source.Length < 27 ||
+ source[4] != '-' ||
+ source[7] != '-' ||
+ source[10] != 'T' ||
+ source[13] != ':' ||
+ source[16] != ':' ||
+ source[19] != '.')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ int year;
+ {
+ uint y1 = (uint)(source[0] - '0'), y2 = (uint)(source[1] - '0'), y3 = (uint)(source[2] - '0'), y4 = (uint)(source[3] - '0');
+
+ if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ year = (int)(y1*1000 + y2*100 + y3*10 + y4);
+ }
+
+ int month;
+ {
+ uint m1 = (uint)(source[5] - '0'), m2 = (uint)(source[6] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ month = (int)(m1*10 + m2);
+ }
+
+ int day;
+ {
+ uint d1 = (uint)(source[8] - '0'), d2 = (uint)(source[9] - '0');
+
+ if (d1 > 9 || d2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ day = (int)(d1*10 + d2);
+ }
+
+ int hour;
+ {
+ uint h1 = (uint)(source[11] - '0'), h2 = (uint)(source[12] - '0');
+
+ if (h1 > 9 || h2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ hour = (int)(h1*10 + h2);
+ }
+
+ int minute;
+ {
+ uint m1 = (uint)(source[14] - '0'), m2 = (uint)(source[15] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ minute = (int)(m1*10 + m2);
+ }
+
+ int second;
+ {
+ uint s1 = (uint)(source[17] - '0'), s2 = (uint)(source[18] - '0');
+
+ if (s1 > 9 || s2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ second = (int)(s1*10 + s2);
+ }
+
+ double fraction;
+ {
+ uint f1 = (uint)(source[20] - '0');
+ uint f2 = (uint)(source[21] - '0');
+ uint f3 = (uint)(source[22] - '0');
+ uint f4 = (uint)(source[23] - '0');
+ uint f5 = (uint)(source[24] - '0');
+ uint f6 = (uint)(source[25] - '0');
+ uint f7 = (uint)(source[26] - '0');
+
+ if (f1 > 9 || f2 > 9 || f3 > 9 || f4 > 9 || f5 > 9 || f6 > 9 || f7 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ fraction = (f1*1000000 + f2*100000 + f3*10000 + f4*1000 + f5*100 + f6*10 + f7) / 10000000.0;
+ }
+
+ if (!DateTime.TryCreate(year, month, day, hour, minute, second, 0, out DateTime dateTime))
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ result.parsedDate = dateTime.AddTicks((long)Math.Round(fraction * Calendar.TicksPerSecond));
+
+ if ((uint)source.Length > 27)
+ {
+ char offsetChar = source[27];
+ switch (offsetChar)
+ {
+ case 'Z':
+ if (source.Length != 28)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ result.flags |= ParseFlags.TimeZoneUsed | ParseFlags.TimeZoneUtc;
+ break;
+
+ case '+':
+ case '-':
+ int offsetHours, colonIndex;
+
+ if ((uint)source.Length == 33)
+ {
+ uint oh1 = (uint)(source[28] - '0'), oh2 = (uint)(source[29] - '0');
+
+ if (oh1 > 9 || oh2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ offsetHours = (int)(oh1 * 10 + oh2);
+ colonIndex = 30;
+ }
+ else if ((uint)source.Length == 32) // special-case allowed for compat: only one offset hour digit
+ {
+ offsetHours = source[28] - '0';
+
+ if ((uint)offsetHours > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ colonIndex = 29;
+ }
+ else
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ if (source[colonIndex] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ int offsetMinutes;
+ {
+ uint om1 = (uint)(source[colonIndex + 1] - '0'), om2 = (uint)(source[colonIndex + 2] - '0');
+
+ if (om1 > 9 || om2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ offsetMinutes = (int)(om1*10 + om2);
+ }
+
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(offsetHours, offsetMinutes, 0);
+ if (offsetChar == '-')
+ {
+ result.timeZoneOffset = result.timeZoneOffset.Negate();
+ }
+ break;
+
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ return DetermineTimeZoneAdjustments(ref result, DateTimeStyles.None, bTimeOnly: false);
+ }
+
private static Exception GetDateTimeParseException(ref DateTimeResult result)
{
switch (result.failure)
@@ -4700,7 +5126,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
private static string Hex(string[] strs)
{
if (strs == null || strs.Length == 0)
- return String.Empty;
+ return string.Empty;
if (strs.Length == 1)
return Hex(strs[0]);
@@ -4713,7 +5139,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
StringBuilder buffer = new StringBuilder();
buffer.Append(Hex(strs[0]));
curLineLength = buffer.Length;
- String s;
+ string s;
for (int i = 1; i < strs.Length - 1; i++)
{
@@ -4766,7 +5192,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return buffer.ToString();
}
// return an unicode escaped string form of char c
- private static String Hex(char c)
+ private static string Hex(char c)
{
if (c <= '\x007f')
return c.ToString(CultureInfo.InvariantCulture);
@@ -4819,20 +5245,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal __DTString(ReadOnlySpan<char> str, DateTimeFormatInfo dtfi)
{
+ Debug.Assert(dtfi != null, "Expected non-null DateTimeFormatInfo");
+
Index = -1;
Value = str;
m_current = '\0';
- if (dtfi != null)
- {
- m_info = dtfi.CompareInfo;
- m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
- }
- else
- {
- m_info = CultureInfo.CurrentCulture.CompareInfo;
- m_checkDigitToken = false;
- }
+ m_info = dtfi.CompareInfo;
+ m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
}
internal CompareInfo CompareInfo
@@ -4954,13 +5374,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
}
- else if (Char.IsWhiteSpace(m_current))
+ else if (char.IsWhiteSpace(m_current))
{
// Just skip to the next character.
while (++Index < Length)
{
m_current = Value[Index];
- if (!(Char.IsWhiteSpace(m_current)))
+ if (!(char.IsWhiteSpace(m_current)))
{
goto Start;
}
@@ -5004,13 +5424,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool MatchSpecifiedWord(String target) =>
+ internal bool MatchSpecifiedWord(string target) =>
Index + target.Length <= Length &&
m_info.Compare(Value.Slice(Index, target.Length), target, CompareOptions.IgnoreCase) == 0;
- private static readonly Char[] WhiteSpaceChecks = new Char[] { ' ', '\u00A0' };
+ private static readonly char[] WhiteSpaceChecks = new char[] { ' ', '\u00A0' };
- internal bool MatchSpecifiedWords(String target, bool checkWordBoundary, ref int matchLength)
+ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int matchLength)
{
int valueRemaining = Value.Length - Index;
matchLength = target.Length;
@@ -5041,11 +5461,11 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
else
{
// Make sure we also have whitespace in the input string
- if (!Char.IsWhiteSpace(Value[thisPosition + segmentLength]))
+ if (!char.IsWhiteSpace(Value[thisPosition + segmentLength]))
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5057,7 +5477,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Skip past multiple whitespace
- while (thisPosition < Value.Length && Char.IsWhiteSpace(Value[thisPosition]))
+ while (thisPosition < Value.Length && char.IsWhiteSpace(Value[thisPosition]))
{
thisPosition++;
matchLength++;
@@ -5071,7 +5491,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5083,7 +5503,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int nextCharIndex = Index + matchLength;
if (nextCharIndex < Value.Length)
{
- if (Char.IsLetter(Value[nextCharIndex]))
+ if (char.IsLetter(Value[nextCharIndex]))
{
return (false);
}
@@ -5098,7 +5518,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// If a match is found, true value is returned and Index is updated to the next character to be parsed.
// Otherwise, Index is unchanged.
//
- internal bool Match(String str)
+ internal bool Match(string str)
{
if (++Index >= Length)
{
@@ -5147,12 +5567,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// maxMatchStrLen [in/out] the initailized maximum length. This parameter can be used to
// find the longest match in two string arrays.
//
- internal int MatchLongestWords(String[] words, ref int maxMatchStrLen)
+ internal int MatchLongestWords(string[] words, ref int maxMatchStrLen)
{
int result = -1;
for (int i = 0; i < words.Length; i++)
{
- String word = words[i];
+ string word = words[i];
int matchLength = word.Length;
if (MatchSpecifiedWords(word, false, ref matchLength))
{
@@ -5225,7 +5645,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (Index + 1 < Length)
{
char ch = Value[Index + 1];
- if (!Char.IsWhiteSpace(ch))
+ if (!char.IsWhiteSpace(ch))
{
return;
}
@@ -5246,7 +5666,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return (false);
}
- if (!Char.IsWhiteSpace(m_current))
+ if (!char.IsWhiteSpace(m_current))
{
return (true);
}
@@ -5254,7 +5674,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (++Index < Length)
{
m_current = Value[Index];
- if (!Char.IsWhiteSpace(m_current))
+ if (!char.IsWhiteSpace(m_current))
{
return (true);
}
@@ -5266,7 +5686,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal void TrimTail()
{
int i = Length - 1;
- while (i >= 0 && Char.IsWhiteSpace(Value[i]))
+ while (i >= 0 && char.IsWhiteSpace(Value[i]))
{
i--;
}
@@ -5286,14 +5706,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- if (Char.IsWhiteSpace(Value[i - 1]))
+ if (char.IsWhiteSpace(Value[i - 1]))
{
i--;
- while (i >= 1 && Char.IsWhiteSpace(Value[i - 1]))
+ while (i >= 1 && char.IsWhiteSpace(Value[i - 1]))
{
i--;
}
- Value = Value.Remove(i, Value.Length - 1 - i);
+ Span<char> result = new char[i + 1];
+ result[i] = ch;
+ Value.Slice(0, i).CopyTo(result);
+ Value = result;
}
}
}
@@ -5311,13 +5734,16 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- while ((i + 1) < Length && Char.IsWhiteSpace(Value[i + 1]))
+ while ((i + 1) < Length && char.IsWhiteSpace(Value[i + 1]))
{
i++;
}
if (i != 0)
{
- Value = Value.Remove(1, i);
+ Span<char> result = new char[Value.Length - i];
+ result[0] = ch;
+ Value.Slice(i + 1).CopyTo(result.Slice(1));
+ Value = result;
}
}
}
@@ -5330,7 +5756,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (Index + sub.length < Length)
{
DTSubStringType currentType;
- Char ch = Value[Index + sub.length];
+ char ch = Value[Index + sub.length];
if (ch >= '0' && ch <= '9')
{
currentType = DTSubStringType.Number;
@@ -5406,12 +5832,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal ref struct DTSubString
{
internal ReadOnlySpan<char> s;
- internal Int32 index;
- internal Int32 length;
+ internal int index;
+ internal int length;
internal DTSubStringType type;
- internal Int32 value;
+ internal int value;
- internal Char this[Int32 relativeIndex]
+ internal char this[int relativeIndex]
{
get
{
@@ -5510,7 +5936,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal int Month;
internal int Day;
//
- // Set time defualt to 00:00:00.
+ // Set time default to 00:00:00.
//
internal int Hour;
internal int Minute;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs b/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
index e6920b366..72a572c97 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
@@ -11,10 +11,6 @@ namespace System.Globalization
private readonly DateTime _end;
private readonly TimeSpan _delta;
- private DaylightTime()
- {
- }
-
public DaylightTime(DateTime start, DateTime end, TimeSpan delta)
{
_start = start;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
index 358f4df18..a29f8a1ee 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
@@ -162,7 +162,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange,
+ string.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange,
MinSupportedDateTime, MaxSupportedDateTime));
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
index 16023209e..6b08ee540 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
@@ -20,8 +20,14 @@ namespace System.Globalization
public const int ADEra = 1;
//
- // This is the max Gregorian year can be represented by DateTime class. The limitation
- // is derived from DateTime class.
+ // This is the min Gregorian year can be represented by the DateTime class.
+ // The limitation is derived from the DateTime class.
+ //
+ internal const int MinYear = 1;
+
+ //
+ // This is the max Gregorian year can be represented by the DateTime class.
+ // The limitation is derived from the DateTime class.
//
internal const int MaxYear = 9999;
@@ -206,7 +212,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -317,7 +323,7 @@ namespace System.Globalization
}
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -364,7 +370,7 @@ namespace System.Globalization
}
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -451,7 +457,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
@@ -473,7 +479,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
@@ -501,7 +507,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
@@ -520,25 +526,11 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
- internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
+ internal override bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
{
if (era == CurrentEra || era == ADEra)
{
- try
- {
- result = new DateTime(year, month, day, hour, minute, second, millisecond);
- return true;
- }
- catch (ArgumentOutOfRangeException)
- {
- result = DateTime.Now;
- return false;
- }
- catch (ArgumentException)
- {
- result = DateTime.Now;
- return false;
- }
+ return DateTime.TryCreate(year, month, day, hour, minute, second, millisecond, out result);
}
result = DateTime.MinValue;
return false;
@@ -565,7 +557,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -588,7 +580,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
index 2842bd3a1..34206b380 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
@@ -19,9 +19,9 @@ namespace System.Globalization
// be affected by the DateTime.MinValue;
internal int maxEraYear; // Max year value in this era. (== the year length of the era + 1)
- internal String eraName; // The era name
- internal String abbrevEraName; // Abbreviated Era Name
- internal String englishEraName; // English era name
+ internal string eraName; // The era name
+ internal string abbrevEraName; // Abbreviated Era Name
+ internal string englishEraName; // English era name
internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear)
{
@@ -33,7 +33,7 @@ namespace System.Globalization
}
internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear,
- String eraName, String abbrevEraName, String englishEraName)
+ string eraName, string abbrevEraName, string englishEraName)
{
this.era = era;
this.yearOffset = yearOffset;
@@ -47,8 +47,8 @@ namespace System.Globalization
}
// This calendar recognizes two era values:
- // 0 CurrentEra (AD)
- // 1 BeforeCurrentEra (BC)
+ // 0 CurrentEra (AD)
+ // 1 BeforeCurrentEra (BC)
internal class GregorianCalendarHelper
{
// 1 tick = 100ns = 10E-7 second
@@ -87,7 +87,7 @@ namespace System.Globalization
//
// This is the max Gregorian year can be represented by DateTime class. The limitation
// is derived from DateTime class.
- //
+ //
internal int MaxYear
{
get
@@ -123,22 +123,19 @@ namespace System.Globalization
m_minYear = m_EraInfo[0].minEraYear; ;
}
- /*=================================GetGregorianYear==========================
- **Action: Get the Gregorian year value for the specified year in an era.
- **Returns: The Gregorian year value.
- **Arguments:
- ** year the year value in Japanese calendar
- ** era the Japanese emperor era value.
- **Exceptions:
- ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
- ============================================================================*/
-
- internal int GetGregorianYear(int year, int era)
+ // EraInfo.yearOffset: The offset to Gregorian year when the era starts. Gregorian Year = Era Year + yearOffset
+ // Era Year = Gregorian Year - yearOffset
+ // EraInfo.minEraYear: Min year value in this era. Generally, this value is 1, but this may be affected by the DateTime.MinValue;
+ // EraInfo.maxEraYear: Max year value in this era. (== the year length of the era + 1)
+ private int GetYearOffset(int year, int era, bool throwOnError)
{
if (year < 0)
{
- throw new ArgumentOutOfRangeException(nameof(year),
- SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (throwOnError)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ return -1;
}
if (era == Calendar.CurrentEra)
@@ -150,48 +147,78 @@ namespace System.Globalization
{
if (era == m_EraInfo[i].era)
{
- if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear)
+ if (year >= m_EraInfo[i].minEraYear)
+ {
+ if (year <= m_EraInfo[i].maxEraYear)
+ {
+ return m_EraInfo[i].yearOffset;
+ }
+ else if (!AppContextSwitches.EnforceJapaneseEraYearRanges)
+ {
+ // If we got the year number exceeding the era max year number, this still possible be valid as the date can be created before
+ // introducing new eras after the era we are checking. we'll loop on the eras after the era we have and ensure the year
+ // can exist in one of these eras. otherwise, we'll throw.
+ // Note, we always return the offset associated with the requested era.
+ //
+ // Here is some example:
+ // if we are getting the era number 4 (Heisei) and getting the year number 32. if the era 4 has year range from 1 to 31
+ // then year 32 exceeded the range of era 4 and we'll try to find out if the years difference (32 - 31 = 1) would lay in
+ // the subsequent eras (e.g era 5 and up)
+
+ int remainingYears = year - m_EraInfo[i].maxEraYear;
+
+ for (int j = i - 1; j >= 0; j--)
+ {
+ if (remainingYears <= m_EraInfo[j].maxEraYear)
+ {
+ return m_EraInfo[i].yearOffset;
+ }
+ remainingYears -= m_EraInfo[j].maxEraYear;
+ }
+ }
+ }
+
+ if (throwOnError)
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
m_EraInfo[i].minEraYear,
m_EraInfo[i].maxEraYear));
}
- return (m_EraInfo[i].yearOffset + year);
+
+ break; // no need to iterate more on eras.
}
}
- throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
- }
- internal bool IsValidYear(int year, int era)
- {
- if (year < 0)
+ if (throwOnError)
{
- return false;
+ throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
+ return -1;
+ }
- if (era == Calendar.CurrentEra)
- {
- era = m_Cal.CurrentEraValue;
- }
+ /*=================================GetGregorianYear==========================
+ **Action: Get the Gregorian year value for the specified year in an era.
+ **Returns: The Gregorian year value.
+ **Arguments:
+ ** year the year value in Japanese calendar
+ ** era the Japanese emperor era value.
+ **Exceptions:
+ ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
+ ============================================================================*/
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- if (era == m_EraInfo[i].era)
- {
- if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear)
- {
- return false;
- }
- return true;
- }
- }
- return false;
+ internal int GetGregorianYear(int year, int era)
+ {
+ return GetYearOffset(year, era, throwOnError: true) + year;
}
+ internal bool IsValidYear(int year, int era)
+ {
+ return GetYearOffset(year, era, throwOnError: false) >= 0;
+ }
// Returns a given date part of this DateTime. This method is used
// to compute the year, day-of-year, month, or day part.
@@ -297,7 +324,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(millisecond),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -315,7 +342,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
m_Cal.MinSupportedDateTime,
@@ -346,7 +373,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -544,7 +571,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -583,7 +610,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -638,7 +665,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear));
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
index 533d3831b..06807811e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
@@ -100,7 +100,7 @@ namespace System.Globalization
A 99 means the year is not supported for translation.
for convenience the table was defined for 750 year,
but only 640 years are supported. (from 1583 to 2239)
- the years before 1582 (starting of Georgian calander)
+ the years before 1582 (starting of Georgian calendar)
and after 2239, are filled with 99.
Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
@@ -344,14 +344,14 @@ namespace System.Globalization
** We use a table for the Hebrew calendar calculation, so the year supported is limited.
============================================================================*/
- private static void CheckHebrewYearValue(int y, int era, String varName)
+ private static void CheckHebrewYearValue(int y, int era, string varName)
{
CheckEraRange(era);
if (y > MaxHebrewYear || y < MinHebrewYear)
{
throw new ArgumentOutOfRangeException(
varName,
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinHebrewYear,
@@ -376,7 +376,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -402,7 +402,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -425,7 +425,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(
"time",
// Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar.
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
calendarMinValue,
@@ -708,7 +708,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_AddValue));
}
@@ -1104,7 +1104,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinHebrewYear,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs b/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
index 1e8fff2bc..4413cd9fa 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
@@ -87,7 +87,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- internal static String ToString(int Number)
+ internal static string ToString(int Number)
{
char cTens = '\x0';
char cUnits; // tens and units chars
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
index 365942cce..7333f87d5 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
@@ -10,7 +10,7 @@ namespace System.Globalization
{
private int GetHijriDateAdjustment()
{
- if (_hijriAdvance == Int32.MinValue)
+ if (_hijriAdvance == int.MinValue)
{
// Never been set before. Use the system value from registry.
_hijriAdvance = GetAdvanceHijriDate();
@@ -18,8 +18,8 @@ namespace System.Globalization
return (_hijriAdvance);
}
- private const String InternationalRegKey = "Control Panel\\International";
- private const String HijriAdvanceRegKeyEntry = "AddHijriDate";
+ private const string InternationalRegKey = "Control Panel\\International";
+ private const string HijriAdvanceRegKeyEntry = "AddHijriDate";
/*=================================GetAdvanceHijriDate==========================
**Action: Gets the AddHijriDate value from the registry.
@@ -45,7 +45,7 @@ namespace System.Globalization
try
{
// Open in read-only mode.
- key = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER).OpenSubKey(InternationalRegKey, false);
+ key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser).OpenSubKey(InternationalRegKey, false);
}
//If this fails for any reason, we'll just return 0.
catch (ObjectDisposedException) { return 0; }
@@ -55,13 +55,13 @@ namespace System.Globalization
{
try
{
- Object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false);
+ object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false);
if (value == null)
{
return (0);
}
- String str = value.ToString();
- if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0)
+ string str = value.ToString();
+ if (string.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0)
{
if (str.Length == HijriAdvanceRegKeyEntry.Length)
hijriAdvance = -1;
@@ -69,7 +69,7 @@ namespace System.Globalization
{
try
{
- int advance = Int32.Parse(str.AsSpan().Slice(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
+ int advance = int.Parse(str.AsSpan(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri))
{
hijriAdvance = advance;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
index 675584462..3eaf3d253 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
@@ -55,7 +55,7 @@ namespace System.Globalization
internal static readonly int[] HijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 };
- private int _hijriAdvance = Int32.MinValue;
+ private int _hijriAdvance = int.MinValue;
// DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3).
internal const int MaxCalendarYear = 9666;
@@ -176,7 +176,7 @@ namespace System.Globalization
{
get
{
- if (_hijriAdvance == Int32.MinValue)
+ if (_hijriAdvance == int.MinValue)
{
// Never been set before. Use the system value from registry.
_hijriAdvance = GetHijriDateAdjustment();
@@ -191,7 +191,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"HijriAdjustment",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Bounds_Lower_Upper,
MinAdvancedHijri,
@@ -209,7 +209,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
calendarMinValue,
@@ -232,7 +232,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -249,7 +249,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -387,7 +387,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -541,7 +541,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -591,7 +591,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -631,7 +631,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(value),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -659,7 +659,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs b/src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs
new file mode 100644
index 000000000..3b3ba15ec
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs
@@ -0,0 +1,162 @@
+// 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 static System.Globalization.GregorianCalendar;
+
+namespace System.Globalization
+{
+ public static class ISOWeek
+ {
+ private const int WeeksInLongYear = 53;
+ private const int WeeksInShortYear = 52;
+
+ private const int MinWeek = 1;
+ private const int MaxWeek = WeeksInLongYear;
+
+ public static int GetWeekOfYear(DateTime date)
+ {
+ int week = GetWeekNumber(date);
+
+ if (week < MinWeek)
+ {
+ // If the week number obtained equals 0, it means that the
+ // given date belongs to the preceding (week-based) year.
+ return GetWeeksInYear(date.Year - 1);
+ }
+
+ if (week > GetWeeksInYear(date.Year))
+ {
+ // If a week number of 53 is obtained, one must check that
+ // the date is not actually in week 1 of the following year.
+ return MinWeek;
+ }
+
+ return week;
+ }
+
+ public static int GetYear(DateTime date)
+ {
+ int week = GetWeekNumber(date);
+
+ if (week < MinWeek)
+ {
+ // If the week number obtained equals 0, it means that the
+ // given date belongs to the preceding (week-based) year.
+ return date.Year - 1;
+ }
+
+ if (week > GetWeeksInYear(date.Year))
+ {
+ // If a week number of 53 is obtained, one must check that
+ // the date is not actually in week 1 of the following year.
+ return date.Year + 1;
+ }
+
+ return date.Year;
+ }
+
+ // The year parameter represents an ISO week-numbering year (also called ISO year informally).
+ // Each week's year is the Gregorian year in which the Thursday falls.
+ // The first week of the year, hence, always contains 4 January.
+ // ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
+ public static DateTime GetYearStart(int year)
+ {
+ return ToDateTime(year, MinWeek, DayOfWeek.Monday);
+ }
+
+ // The year parameter represents an ISO week-numbering year (also called ISO year informally).
+ // Each week's year is the Gregorian year in which the Thursday falls.
+ // The first week of the year, hence, always contains 4 January.
+ // ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
+ public static DateTime GetYearEnd(int year)
+ {
+ return ToDateTime(year, GetWeeksInYear(year), DayOfWeek.Sunday);
+ }
+
+ // From https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year:
+ //
+ // The long years, with 53 weeks in them, can be described by any of the following equivalent definitions:
+ //
+ // - Any year starting on Thursday and any leap year starting on Wednesday.
+ // - Any year ending on Thursday and any leap year ending on Friday.
+ // - Years in which 1 January and 31 December (in common years) or either (in leap years) are Thursdays.
+ //
+ // All other week-numbering years are short years and have 52 weeks.
+ public static int GetWeeksInYear(int year)
+ {
+ if (year < MinYear || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
+ }
+
+ int P(int y) => (y + (y / 4) - (y / 100) + (y / 400)) % 7;
+
+ if (P(year) == 4 || P(year - 1) == 3)
+ {
+ return WeeksInLongYear;
+ }
+
+ return WeeksInShortYear;
+ }
+
+ // From https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year,_week_number_and_weekday:
+ //
+ // This method requires that one know the weekday of 4 January of the year in question.
+ // Add 3 to the number of this weekday, giving a correction to be used for dates within this year.
+ //
+ // Multiply the week number by 7, then add the weekday. From this sum subtract the correction for the year.
+ // The result is the ordinal date, which can be converted into a calendar date.
+ //
+ // If the ordinal date thus obtained is zero or negative, the date belongs to the previous calendar year.
+ // If greater than the number of days in the year, to the following year.
+ public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek)
+ {
+ if (year < MinYear || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
+ }
+
+ if (week < MinWeek || week > MaxWeek)
+ {
+ throw new ArgumentOutOfRangeException(nameof(week), SR.ArgumentOutOfRange_Week_ISO);
+ }
+
+ // We allow 7 for convenience in cases where a user already has a valid ISO
+ // day of week value for Sunday. This means that both 0 and 7 will map to Sunday.
+ // The GetWeekday method will normalize this into the 1-7 range required by ISO.
+ if ((int)dayOfWeek < 0 || (int)dayOfWeek > 7)
+ {
+ throw new ArgumentOutOfRangeException(nameof(dayOfWeek), SR.ArgumentOutOfRange_DayOfWeek);
+ }
+
+ var jan4 = new DateTime(year, month: 1, day: 4);
+
+ int correction = GetWeekday(jan4.DayOfWeek) + 3;
+
+ int ordinal = (week * 7) + GetWeekday(dayOfWeek) - correction;
+
+ return new DateTime(year, month: 1, day: 1).AddDays(ordinal - 1);
+ }
+
+ // From https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_of_a_given_date:
+ //
+ // Using ISO weekday numbers (running from 1 for Monday to 7 for Sunday),
+ // subtract the weekday from the ordinal date, then add 10. Divide the result by 7.
+ // Ignore the remainder; the quotient equals the week number.
+ //
+ // If the week number thus obtained equals 0, it means that the given date belongs to the preceding (week-based) year.
+ // If a week number of 53 is obtained, one must check that the date is not actually in week 1 of the following year.
+ private static int GetWeekNumber(DateTime date)
+ {
+ return (date.DayOfYear - GetWeekday(date.DayOfWeek) + 10) / 7;
+ }
+
+ // Day of week in ISO is represented by an integer from 1 through 7, beginning with Monday and ending with Sunday.
+ // This matches the underlying values of the DayOfWeek enum, except for Sunday, which needs to be converted.
+ private static int GetWeekday(DayOfWeek dayOfWeek)
+ {
+ return dayOfWeek == DayOfWeek.Sunday ? 7 : (int) dayOfWeek;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
index 5320936a7..20f753e98 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
@@ -8,9 +8,10 @@ namespace System.Globalization
{
sealed partial class IdnMapping
{
- private unsafe string GetAsciiCore(char* unicode, int count)
+ private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(unicodeString != null && unicodeString.Length >= count);
uint flags = Flags;
CheckInvalidIdnCharacters(unicode, count, flags, nameof(unicode));
@@ -26,7 +27,7 @@ namespace System.Globalization
actualLength = Interop.Globalization.ToAscii(flags, unicode, count, outputStack, estimatedLength);
if (actualLength > 0 && actualLength <= estimatedLength)
{
- return new string(outputStack, 0, actualLength);
+ return GetStringForOutput(unicodeString, unicode, count, outputStack, actualLength);
}
}
else
@@ -46,13 +47,14 @@ namespace System.Globalization
{
throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(unicode));
}
- return new string(pOutputHeap, 0, actualLength);
+ return GetStringForOutput(unicodeString, unicode, count, pOutputHeap, actualLength);
}
}
- private unsafe string GetUnicodeCore(char* ascii, int count)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
uint flags = Flags;
CheckInvalidIdnCharacters(ascii, count, flags, nameof(ascii));
@@ -61,21 +63,22 @@ namespace System.Globalization
if (count < StackAllocThreshold)
{
char* output = stackalloc char[count];
- return GetUnicodeCore(ascii, count, flags, output, count, reattempt: true);
+ return GetUnicodeCore(asciiString, ascii, count, flags, output, count, reattempt: true);
}
else
{
char[] output = new char[count];
fixed (char* pOutput = &output[0])
{
- return GetUnicodeCore(ascii, count, flags, pOutput, count, reattempt: true);
+ return GetUnicodeCore(asciiString, ascii, count, flags, pOutput, count, reattempt: true);
}
}
}
- private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength, bool reattempt)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count, uint flags, char* output, int outputLength, bool reattempt)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
int realLen = Interop.Globalization.ToUnicode(flags, ascii, count, output, outputLength);
@@ -85,14 +88,14 @@ namespace System.Globalization
}
else if (realLen <= outputLength)
{
- return new string(output, 0, realLen);
+ return GetStringForOutput(asciiString, ascii, count, output, realLen);
}
else if (reattempt)
{
char[] newOutput = new char[realLen];
fixed (char* pNewOutput = newOutput)
{
- return GetUnicodeCore(ascii, count, flags, pNewOutput, realLen, reattempt: false);
+ return GetUnicodeCore(asciiString, ascii, count, flags, pNewOutput, realLen, reattempt: false);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
index 35da7343e..9d491dfbb 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
@@ -9,9 +9,10 @@ namespace System.Globalization
{
public sealed partial class IdnMapping
{
- private unsafe string GetAsciiCore(char* unicode, int count)
+ private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(unicodeString != null && unicodeString.Length >= count);
uint flags = Flags;
@@ -27,21 +28,22 @@ namespace System.Globalization
if (length < StackAllocThreshold)
{
char* output = stackalloc char[length];
- return GetAsciiCore(unicode, count, flags, output, length);
+ return GetAsciiCore(unicodeString, unicode, count, flags, output, length);
}
else
{
char[] output = new char[length];
fixed (char* pOutput = &output[0])
{
- return GetAsciiCore(unicode, count, flags, pOutput, length);
+ return GetAsciiCore(unicodeString, unicode, count, flags, pOutput, length);
}
}
}
- private unsafe string GetAsciiCore(char* unicode, int count, uint flags, char* output, int outputLength)
+ private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count, uint flags, char* output, int outputLength)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(unicodeString != null && unicodeString.Length >= count);
int length = Interop.Normaliz.IdnToAscii(flags, unicode, count, output, outputLength);
if (length == 0)
@@ -49,12 +51,13 @@ namespace System.Globalization
ThrowForZeroLength(unicode: true);
}
Debug.Assert(length == outputLength);
- return new string(output, 0, length);
+ return GetStringForOutput(unicodeString, unicode, count, output, length);
}
- private unsafe string GetUnicodeCore(char* ascii, int count)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
uint flags = Flags;
@@ -70,21 +73,22 @@ namespace System.Globalization
if (length < StackAllocThreshold)
{
char* output = stackalloc char[length];
- return GetUnicodeCore(ascii, count, flags, output, length);
+ return GetUnicodeCore(asciiString, ascii, count, flags, output, length);
}
else
{
char[] output = new char[length];
fixed (char* pOutput = &output[0])
{
- return GetUnicodeCore(ascii, count, flags, pOutput, length);
+ return GetUnicodeCore(asciiString, ascii, count, flags, pOutput, length);
}
}
}
- private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count, uint flags, char* output, int outputLength)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
int length = Interop.Normaliz.IdnToUnicode(flags, ascii, count, output, outputLength);
if (length == 0)
@@ -92,7 +96,7 @@ namespace System.Globalization
ThrowForZeroLength(unicode: false);
}
Debug.Assert(length == outputLength);
- return new string(output, 0, length);
+ return GetStringForOutput(asciiString, ascii, count, output, length);
}
// -----------------------------
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
index 176e5feed..164e46dc8 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
@@ -25,6 +25,7 @@
// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Text;
namespace System.Globalization
@@ -93,7 +94,7 @@ namespace System.Globalization
{
fixed (char* pUnicode = unicode)
{
- return GetAsciiCore(pUnicode + index, count);
+ return GetAsciiCore(unicode, pUnicode + index, count);
}
}
}
@@ -137,7 +138,7 @@ namespace System.Globalization
{
fixed (char* pAscii = ascii)
{
- return GetUnicodeCore(pAscii + index, count);
+ return GetUnicodeCore(ascii, pAscii + index, count);
}
}
}
@@ -156,6 +157,14 @@ namespace System.Globalization
return (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static unsafe string GetStringForOutput(string originalString, char* input, int inputLength, char* output, int outputLength)
+ {
+ return originalString.Length == inputLength && new ReadOnlySpan<char>(input, inputLength).SequenceEqual(new ReadOnlySpan<char>(output, outputLength)) ?
+ originalString :
+ new string(output, 0, outputLength);
+ }
+
//
// Invariant implementation
//
@@ -272,7 +281,7 @@ namespace System.Globalization
// Need to validate entire string length, 1 shorter if last char wasn't a dot
if (unicode.Length > c_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
+ throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
c_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1)), nameof(unicode));
// If last char wasn't a dot we need to check for trailing -
@@ -352,7 +361,7 @@ namespace System.Globalization
// Check last char
int iTest = iNextDot - 1;
- if (Char.IsLowSurrogate(unicode, iTest))
+ if (char.IsLowSurrogate(unicode, iTest))
{
iTest--;
}
@@ -371,7 +380,7 @@ namespace System.Globalization
for (basicCount = iAfterLastDot; basicCount < iNextDot; basicCount++)
{
// Can't be lonely surrogate because it would've thrown in normalization
- Debug.Assert(Char.IsLowSurrogate(unicode, basicCount) == false, "[IdnMapping.punycode_encode]Unexpected low surrogate");
+ Debug.Assert(char.IsLowSurrogate(unicode, basicCount) == false, "[IdnMapping.punycode_encode]Unexpected low surrogate");
// Double check our bidi rules
BidiCategory testBidi = CharUnicodeInfo.GetBidiCategory(unicode, basicCount);
@@ -397,7 +406,7 @@ namespace System.Globalization
numProcessed++;
}
// If its a surrogate, skip the next since our bidi category tester doesn't handle it.
- else if (Char.IsSurrogatePair(unicode, basicCount))
+ else if (char.IsSurrogatePair(unicode, basicCount))
basicCount++;
}
@@ -443,7 +452,7 @@ namespace System.Globalization
j < iNextDot;
j += IsSupplementary(test) ? 2 : 1)
{
- test = Char.ConvertToUtf32(unicode, j);
+ test = char.ConvertToUtf32(unicode, j);
if (test >= n && test < m) m = test;
}
@@ -456,7 +465,7 @@ namespace System.Globalization
for (j = iAfterLastDot; j < iNextDot; j+= IsSupplementary(test) ? 2 : 1)
{
// Make sure we're aware of surrogates
- test = Char.ConvertToUtf32(unicode, j);
+ test = char.ConvertToUtf32(unicode, j);
// Adjust for character position (only the chars in our string already, some
// haven't been processed.
@@ -512,7 +521,7 @@ namespace System.Globalization
// Throw if we're too long
if (output.Length > c_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
+ throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
c_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1)), nameof(unicode));
// Return our output string
return output.ToString();
@@ -594,7 +603,7 @@ namespace System.Globalization
// Throw if we're too long
if (ascii.Length > c_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
+ throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
c_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1)), nameof(ascii));
// output stringbuilder
@@ -628,11 +637,11 @@ namespace System.Globalization
throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(ascii));
// See if this section's ASCII or ACE
- if (ascii.Length < c_strAcePrefix.Length + iAfterLastDot ||
- !ascii.Substring(iAfterLastDot,c_strAcePrefix.Length).Equals(c_strAcePrefix, StringComparison.OrdinalIgnoreCase))
+ if (ascii.Length < c_strAcePrefix.Length + iAfterLastDot ||
+ string.Compare(ascii, iAfterLastDot, c_strAcePrefix, 0, c_strAcePrefix.Length, StringComparison.OrdinalIgnoreCase) != 0)
{
// Its ASCII, copy it
- output.Append(ascii.Substring(iAfterLastDot, iNextDot - iAfterLastDot));
+ output.Append(ascii, iAfterLastDot, iNextDot - iAfterLastDot);
}
else
{
@@ -706,7 +715,7 @@ namespace System.Globalization
i += (int)(digit * w);
int t = k <= bias ? c_tmin : k >= bias + c_tmax ? c_tmax : k - bias;
- if (digit < t)
+ if (digit < t)
break;
Debug.Assert(c_punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != c_punycodeBase (36)");
if (w > c_maxint / (c_punycodeBase - t))
@@ -731,7 +740,7 @@ namespace System.Globalization
// insert n at position i of the output: Really tricky if we have surrogates
int iUseInsertLocation;
- String strTemp = Char.ConvertFromUtf32(n);
+ string strTemp = char.ConvertFromUtf32(n);
// If we have supplimentary characters
if (numSurrogatePairs > 0)
@@ -743,7 +752,7 @@ namespace System.Globalization
// If its a surrogate, we have to go one more
if (iUseInsertLocation >= output.Length)
throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
- if (Char.IsSurrogate(output[iUseInsertLocation]))
+ if (char.IsSurrogate(output[iUseInsertLocation]))
iUseInsertLocation++;
}
}
@@ -768,7 +777,7 @@ namespace System.Globalization
bool bRightToLeft = false;
// Check for RTL. If right-to-left, then 1st & last chars must be RTL
- BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iOutputAfterLastDot);
+ BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output, iOutputAfterLastDot);
if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)
{
// It has to be right to left.
@@ -779,11 +788,11 @@ namespace System.Globalization
for (int iTest = iOutputAfterLastDot; iTest < output.Length; iTest++)
{
// This might happen if we run into a pair
- if (Char.IsLowSurrogate(output.ToString(), iTest))
+ if (char.IsLowSurrogate(output[iTest]))
continue;
// Check to see if its LTR
- eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iTest);
+ eBidi = CharUnicodeInfo.GetBidiCategory(output, iTest);
if ((bRightToLeft && eBidi == BidiCategory.LeftToRight) ||
(!bRightToLeft && (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)))
throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(ascii));
@@ -888,6 +897,5 @@ namespace System.Globalization
// 0-25 map to a-z or A-Z
return (char)(d + 'a');
}
-
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs b/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
index 60abcecf6..6dc2b1951 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
@@ -25,8 +25,8 @@ namespace System.Globalization
internal const long TicksPerMillisecond = 10000;
internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
internal const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
- internal const long MaxSeconds = Int64.MaxValue / TicksPerSecond;
- internal const long MinSeconds = Int64.MinValue / TicksPerSecond;
+ internal const long MaxSeconds = long.MaxValue / TicksPerSecond;
+ internal const long MinSeconds = long.MinValue / TicksPerSecond;
private const int DaysPerYear = 365;
private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
@@ -37,12 +37,12 @@ namespace System.Globalization
private const long TicksPerDay = TicksPerHour * 24;
internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
internal const long MinTicks = 0;
- internal const long MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
- internal const long MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
+ internal const long MaxMilliSeconds = long.MaxValue / TicksPerMillisecond;
+ internal const long MinMilliSeconds = long.MinValue / TicksPerMillisecond;
internal const int StringBuilderDefaultCapacity = 16;
- internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
- internal const Int64 MinOffset = -MaxOffset;
+ internal const long MaxOffset = TimeSpan.TicksPerHour * 14;
+ internal const long MinOffset = -MaxOffset;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
index 1d0180b00..2356afe35 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
@@ -37,13 +37,13 @@ namespace System.Globalization
try
{
// Need to access registry
- RegistryKey key = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE).OpenSubKey(c_japaneseErasHive, false);
+ RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine).OpenSubKey(c_japaneseErasHive, false);
// Abort if we didn't find anything
if (key == null) return null;
// Look up the values in our reg key
- String[] valueNames = key.GetValueNames();
+ string[] valueNames = key.GetValueNames();
if (valueNames != null && valueNames.Length > 0)
{
registryEraRanges = new EraInfo[valueNames.Length];
@@ -143,7 +143,7 @@ namespace System.Globalization
// . is a delimiter, but the value of . doesn't matter.
// '_' marks the space between the japanese era name, japanese abbreviated era name
// english name, and abbreviated english names.
- private static EraInfo GetEraFromValue(String value, String data)
+ private static EraInfo GetEraFromValue(string value, string data)
{
// Need inputs
if (value == null || data == null) return null;
@@ -160,9 +160,9 @@ namespace System.Globalization
int day;
ReadOnlySpan<char> valueSpan = value.AsSpan();
- if (!Int32.TryParse(valueSpan.Slice(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
- !Int32.TryParse(valueSpan.Slice(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
- !Int32.TryParse(valueSpan.Slice(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
+ if (!int.TryParse(valueSpan.Slice(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
+ !int.TryParse(valueSpan.Slice(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
+ !int.TryParse(valueSpan.Slice(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
{
// Couldn't convert integer, fail
return null;
@@ -172,7 +172,7 @@ namespace System.Globalization
// Get Strings
//
// Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups)
- String[] names = data.Split('_');
+ string[] names = data.Split('_');
// Should have exactly 4 parts
// 0 - Era Name
@@ -199,7 +199,7 @@ namespace System.Globalization
// PAL Layer ends here
- private static string[] s_japaneseErasEnglishNames = new String[] { "M", "T", "S", "H" };
+ private static string[] s_japaneseErasEnglishNames = new string[] { "M", "T", "S", "H" };
private static string GetJapaneseEnglishEraName(int era)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs
index 6a9df9720..818cb5b42 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs
@@ -46,7 +46,7 @@ namespace System.Globalization
// PAL Layer ends here
- private static string[] JapaneseErasEnglishNames = new String[] { "M", "T", "S", "H" };
+ private static string[] JapaneseErasEnglishNames = new string[] { "M", "T", "S", "H" };
private static string GetJapaneseEnglishEraName(int era)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
index 50195d7f1..fdf2dc670 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
@@ -303,7 +303,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -325,10 +325,10 @@ namespace System.Globalization
// Return the various era strings
// Note: The arrays are backwards of the eras
//
- internal static String[] EraNames()
+ internal static string[] EraNames()
{
EraInfo[] eras = GetEraInfo();
- String[] eraNames = new String[eras.Length];
+ string[] eraNames = new string[eras.Length];
for (int i = 0; i < eras.Length; i++)
{
@@ -339,10 +339,10 @@ namespace System.Globalization
return eraNames;
}
- internal static String[] AbbrevEraNames()
+ internal static string[] AbbrevEraNames()
{
EraInfo[] eras = GetEraInfo();
- String[] erasAbbrev = new String[eras.Length];
+ string[] erasAbbrev = new string[eras.Length];
for (int i = 0; i < eras.Length; i++)
{
@@ -353,10 +353,10 @@ namespace System.Globalization
return erasAbbrev;
}
- internal static String[] EnglishEraNames()
+ internal static string[] EnglishEraNames()
{
EraInfo[] eras = GetEraInfo();
- String[] erasEnglish = new String[eras.Length];
+ string[] erasEnglish = new string[eras.Length];
for (int i = 0; i < eras.Length; i++)
{
@@ -392,7 +392,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
index e8a2dcd63..64aa79d87 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
@@ -62,101 +62,103 @@ namespace System.Globalization
}
}
+ // Data for years 1960-2049 matches output of Calendrical Calculations [1] and published calendar tables [2].
+ // [1] Reingold, Edward M, and Nachum Dershowitz. Calendrical Calculations: The Ultimate Edition. Cambridge [etc.: Cambridge University Press, 2018. Print.
+ // [2] Nishizawa, Yūsō. Rekijitsu Taikan: Meiji Kaireki 1873-Nen-2100-Nen Shinkyūreki, Kanshi Kyūsei Rokuyō Taishō. Tōkyō: Shin Jinbutsu Ōraisha, 1994. Print.
private static readonly int[,] s_yinfo =
{
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 1960 */
- { 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */{ 0 , 2 , 5 , 19808 },/* 29 30 29 29 30 30 29 30 29 30 30 29 0 354
-1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
-2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
-2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
-2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
-2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
- */ };
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1965 */ { 00, 02, 02, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1966 */ { 03, 01, 22, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1968 */ { 07, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1970 */ { 00, 02, 06, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1973 */ { 00, 02, 03, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1976 */ { 08, 01, 31, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1978 */ { 00, 02, 07, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1982 */ { 04, 01, 25, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1987 */ { 06, 01, 29, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1989 */ { 00, 02, 06, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1990 */ { 05, 01, 27, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1995 */ { 08, 01, 31, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */ { 00, 02, 19, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1997 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1998 */ { 05, 01, 28, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2001 */ { 04, 01, 24, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */ { 00, 02, 09, 0b0101011011000000 }, /* 29 30 29 30 29 30 30 29 30 30 29 29 354
+2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2012 */ { 03, 01, 23, 0b1011101001010000 }, /* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */ { 00, 02, 10, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
+2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2017 */ { 05, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2019 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2020 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2023 */ { 02, 01, 22, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */ { 00, 02, 17, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+2027 */ { 00, 02, 07, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+2028 */ { 05, 01, 27, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */ { 00, 02, 13, 0b1101100100110000 }, /* 30 30 29 30 30 29 29 30 29 29 30 30 355
+2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+2031 */ { 03, 01, 23, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+2036 */ { 06, 01, 28, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */ { 00, 02, 12, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+2041 */ { 00, 02, 01, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+2046 */ { 00, 02, 06, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */ { 00, 02, 14, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+ */ };
internal override int MinCalendarYear
{
@@ -204,7 +206,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MIN_LUNISOLAR_YEAR,
@@ -261,14 +263,12 @@ namespace System.Globalization
return newEras;
}
-
// Construct an instance of JapaneseLunisolar calendar.
public JapaneseLunisolarCalendar()
{
helper = new GregorianCalendarHelper(this, TrimEras(JapaneseCalendar.GetEraInfo()));
}
-
public override int GetEra(DateTime time)
{
return (helper.GetEra(time));
@@ -290,7 +290,6 @@ namespace System.Globalization
}
}
-
public override int[] Eras
{
get
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
index 82e4d589d..a1ffbeb48 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
@@ -98,7 +98,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -142,7 +142,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -214,7 +214,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -372,7 +372,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(millisecond),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -404,7 +404,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -427,7 +427,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Bounds_Lower_Upper,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
index 9168b664e..3f265f69e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
@@ -237,7 +237,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
index 8cdade866..63636f5e3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
@@ -7,10 +7,10 @@ namespace System.Globalization
{
/*
** Calendar support range:
- ** Calendar Minimum Maximum
- ** ========== ========== ==========
- ** Gregorian 918/02/14 2051/02/10
- ** KoreanLunisolar 918/01/01 2050/13/29
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 918/02/19 2051/02/10
+ ** KoreanLunisolar 918/01/01 2050/13/29
*/
public class KoreanLunisolarCalendar : EastAsianLunisolarCalendar
@@ -26,7 +26,7 @@ namespace System.Globalization
internal const int MIN_GREGORIAN_YEAR = 918;
internal const int MIN_GREGORIAN_MONTH = 2;
- internal const int MIN_GREGORIAN_DAY = 14;
+ internal const int MIN_GREGORIAN_DAY = 19;
internal const int MAX_GREGORIAN_YEAR = 2051;
internal const int MAX_GREGORIAN_MONTH = 2;
@@ -43,8 +43,6 @@ namespace System.Globalization
}
}
-
-
public override DateTime MaxSupportedDateTime
{
get
@@ -63,1145 +61,1146 @@ namespace System.Globalization
}
}
+// Data for years 1391-2050 matches that available from
+// Korea Astronomy and Space Science Institute (KASI)
+// https://astro.kasi.re.kr:444/life/pageView/5
private static readonly int[,] s_yinfo =
{
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 918 */
- { 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-919 */{ 0 , 2 , 4 , 17872 },/* 29 30 29 29 29 30 29 30 30 30 29 30 0 354
-920 */{ 6 , 1 , 24 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
-921 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-922 */{ 0 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-923 */{ 4 , 1 , 20 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-924 */{ 0 , 2 , 8 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-925 */{ 12 , 1 , 27 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
-926 */{ 0 , 2 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-927 */{ 0 , 2 , 5 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-928 */{ 8 , 1 , 26 , 17848 },/* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
-929 */{ 0 , 2 , 13 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-930 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-931 */{ 5 , 1 , 22 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
-932 */{ 0 , 2 , 9 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-933 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-934 */{ 1 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-935 */{ 0 , 2 , 6 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-936 */{ 11 , 1 , 27 , 21344 },/* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
-937 */{ 0 , 2 , 13 , 51904 },/* 30 30 29 29 30 29 30 29 30 30 29 29 0 354
-938 */{ 0 , 2 , 2 , 58720 },/* 30 30 30 29 29 30 29 30 29 30 30 29 0 355
-939 */{ 7 , 1 , 23 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-940 */{ 0 , 2 , 11 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-941 */{ 0 , 1 , 30 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-942 */{ 3 , 1 , 20 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-943 */{ 0 , 2 , 8 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-944 */{ 12 , 1 , 28 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
-945 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-946 */{ 0 , 2 , 5 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-947 */{ 7 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-948 */{ 0 , 2 , 13 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-949 */{ 0 , 2 , 1 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
-950 */{ 5 , 1 , 21 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-951 */{ 0 , 2 , 9 , 45936 },/* 30 29 30 30 29 30 29 30 29 30 29 0 0 325
-952 */{ 0 , 12 , 31 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-953 */{ 1 , 1 , 18 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-954 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-955 */{ 9 , 1 , 27 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-956 */{ 0 , 2 , 15 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-957 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-958 */{ 7 , 1 , 23 , 43672 },/* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
-959 */{ 0 , 2 , 11 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-960 */{ 0 , 1 , 31 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-961 */{ 3 , 1 , 20 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-962 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-963 */{ 12 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-964 */{ 0 , 2 , 16 , 41840 },/* 30 29 30 29 29 29 30 30 29 30 30 30 0 355
-965 */{ 0 , 2 , 5 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 0 354
-966 */{ 8 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-967 */{ 0 , 2 , 12 , 54448 },/* 30 30 29 30 29 30 29 29 30 29 30 30 0 355
-968 */{ 0 , 2 , 2 , 23184 },/* 29 30 29 30 30 29 30 29 30 29 29 30 0 354
-969 */{ 5 , 1 , 21 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-970 */{ 0 , 2 , 9 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-971 */{ 0 , 1 , 30 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-972 */{ 2 , 1 , 19 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-973 */{ 0 , 2 , 6 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
-974 */{ 10 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-975 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-976 */{ 0 , 2 , 3 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-977 */{ 7 , 1 , 22 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
-978 */{ 0 , 2 , 10 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-979 */{ 0 , 1 , 31 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-980 */{ 3 , 1 , 21 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-981 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-982 */{ 12 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-983 */{ 0 , 2 , 16 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-984 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-985 */{ 9 , 1 , 24 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-986 */{ 0 , 2 , 12 , 44192 },/* 30 29 30 29 30 30 29 29 30 29 30 29 0 354
-987 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-988 */{ 5 , 1 , 22 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-989 */{ 0 , 2 , 9 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-990 */{ 0 , 1 , 30 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-991 */{ 2 , 1 , 19 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
-992 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-993 */{ 10 , 1 , 26 , 26968 },/* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
-994 */{ 0 , 2 , 14 , 22864 },/* 29 30 29 30 30 29 29 30 29 30 29 30 0 354
-995 */{ 0 , 2 , 3 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-996 */{ 7 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-997 */{ 0 , 2 , 10 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-998 */{ 0 , 1 , 31 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-999 */{ 3 , 1 , 20 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1000 */{ 0 , 2 , 8 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1001 */{ 12 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
-1002 */{ 0 , 2 , 15 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1003 */{ 0 , 2 , 4 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1004 */{ 9 , 1 , 25 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1005 */{ 0 , 2 , 12 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1006 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1007 */{ 5 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1008 */{ 0 , 2 , 10 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-1009 */{ 0 , 1 , 29 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1010 */{ 2 , 1 , 18 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1011 */{ 0 , 2 , 6 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
-1012 */{ 10 , 1 , 26 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1013 */{ 0 , 2 , 13 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1014 */{ 0 , 2 , 3 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
-1015 */{ 6 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1016 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1017 */{ 0 , 1 , 31 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1018 */{ 4 , 1 , 20 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1019 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1020 */{ 12 , 1 , 28 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
-1021 */{ 0 , 2 , 15 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1022 */{ 0 , 2 , 4 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1023 */{ 9 , 1 , 25 , 11688 },/* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
-1024 */{ 0 , 2 , 13 , 11088 },/* 29 29 30 29 30 29 30 30 29 30 29 30 0 354
-1025 */{ 0 , 2 , 1 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1026 */{ 5 , 1 , 22 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1027 */{ 0 , 2 , 9 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
-1028 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1029 */{ 2 , 1 , 18 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1030 */{ 0 , 2 , 5 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
-1031 */{ 10 , 1 , 26 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-1032 */{ 0 , 2 , 14 , 26320 },/* 29 30 30 29 29 30 30 29 30 30 29 30 0 355
-1033 */{ 0 , 2 , 3 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1034 */{ 6 , 1 , 23 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1035 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1036 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1037 */{ 4 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1038 */{ 0 , 2 , 7 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1039 */{ 12 , 1 , 27 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
-1040 */{ 0 , 2 , 15 , 46464 },/* 30 29 30 30 29 30 29 30 30 29 29 29 0 354
-1041 */{ 0 , 2 , 3 , 54960 },/* 30 30 29 30 29 30 30 29 30 29 30 30 0 356
-1042 */{ 9 , 1 , 25 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
-1043 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1044 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1045 */{ 5 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1046 */{ 0 , 2 , 9 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1047 */{ 0 , 1 , 29 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1048 */{ 1 , 1 , 18 , 46424 },/* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
-1049 */{ 0 , 2 , 6 , 11600 },/* 29 29 30 29 30 30 29 30 29 30 29 30 0 354
-1050 */{ 11 , 1 , 26 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1051 */{ 0 , 2 , 14 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-1052 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-1053 */{ 7 , 1 , 23 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1054 */{ 0 , 2 , 11 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1055 */{ 0 , 1 , 31 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1056 */{ 3 , 1 , 20 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1057 */{ 0 , 2 , 7 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1058 */{ 12 , 1 , 27 , 43864 },/* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
-1059 */{ 0 , 2 , 16 , 10064 },/* 29 29 30 29 29 30 30 30 29 30 29 30 0 354
-1060 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1061 */{ 8 , 1 , 24 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1062 */{ 0 , 2 , 12 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1063 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1064 */{ 5 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1065 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1066 */{ 0 , 1 , 29 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1067 */{ 1 , 1 , 18 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1068 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1069 */{ 11 , 1 , 26 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1070 */{ 0 , 2 , 14 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
-1071 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1072 */{ 7 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1073 */{ 0 , 2 , 10 , 43616 },/* 30 29 30 29 30 29 30 29 29 30 30 29 0 354
-1074 */{ 0 , 1 , 30 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1075 */{ 4 , 1 , 20 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1076 */{ 0 , 2 , 8 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
-1077 */{ 0 , 1 , 27 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1078 */{ 1 , 1 , 17 , 19352 },/* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
-1079 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1080 */{ 9 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1081 */{ 0 , 2 , 12 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1082 */{ 0 , 2 , 1 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1083 */{ 6 , 1 , 21 , 46408 },/* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
-1084 */{ 0 , 2 , 9 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1085 */{ 0 , 1 , 29 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1086 */{ 2 , 1 , 18 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1087 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1088 */{ 12 , 1 , 27 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1089 */{ 0 , 2 , 13 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
-1090 */{ 0 , 2 , 3 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1091 */{ 8 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1092 */{ 0 , 2 , 10 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1093 */{ 0 , 1 , 30 , 23360 },/* 29 30 29 30 30 29 30 30 29 30 29 29 0 354
-1094 */{ 4 , 1 , 19 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
-1095 */{ 0 , 2 , 8 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1096 */{ 0 , 1 , 28 , 58896 },/* 30 30 30 29 29 30 30 29 29 29 29 30 0 354
-1097 */{ 2 , 1 , 16 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1098 */{ 0 , 2 , 4 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1099 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1100 */{ 0 , 2 , 12 , 21664 },/* 29 30 29 30 29 30 29 29 30 29 30 29 0 353
-1101 */{ 0 , 1 , 31 , 54864 },/* 30 30 29 30 29 30 30 29 29 30 29 30 0 355
-1102 */{ 6 , 1 , 21 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1103 */{ 0 , 2 , 9 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1104 */{ 0 , 1 , 30 , 9936 },/* 29 29 30 29 29 30 30 29 30 30 29 30 0 354
-1105 */{ 2 , 1 , 18 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1106 */{ 0 , 2 , 6 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1107 */{ 10 , 1 , 26 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1108 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1109 */{ 0 , 2 , 2 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1110 */{ 8 , 1 , 22 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1111 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1112 */{ 0 , 1 , 31 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1113 */{ 4 , 1 , 20 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1114 */{ 0 , 2 , 8 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1115 */{ 0 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1116 */{ 1 , 1 , 17 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1117 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1118 */{ 9 , 1 , 24 , 29352 },/* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
-1119 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1120 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1121 */{ 5 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1122 */{ 0 , 2 , 9 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1123 */{ 0 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1124 */{ 3 , 1 , 19 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1125 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1126 */{ 11 , 1 , 25 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1127 */{ 0 , 2 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1128 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1129 */{ 8 , 1 , 22 , 39824 },/* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
-1130 */{ 0 , 2 , 10 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1131 */{ 0 , 1 , 31 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1132 */{ 4 , 1 , 20 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1133 */{ 0 , 2 , 7 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1134 */{ 0 , 1 , 27 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1135 */{ 2 , 1 , 16 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
-1136 */{ 0 , 2 , 4 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1137 */{ 10 , 1 , 23 , 54952 },/* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
-1138 */{ 0 , 2 , 12 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1139 */{ 0 , 2 , 1 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1140 */{ 6 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1141 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1142 */{ 0 , 1 , 29 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1143 */{ 4 , 1 , 18 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1144 */{ 0 , 2 , 6 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1145 */{ 11 , 1 , 25 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1146 */{ 0 , 2 , 13 , 27456 },/* 29 30 30 29 30 29 30 30 29 30 29 29 0 354
-1147 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1148 */{ 8 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1149 */{ 0 , 2 , 10 , 39280 },/* 30 29 29 30 30 29 29 30 29 30 30 30 0 355
-1150 */{ 0 , 1 , 31 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1151 */{ 4 , 1 , 20 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1152 */{ 0 , 2 , 8 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
-1153 */{ 12 , 1 , 27 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1154 */{ 0 , 2 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1155 */{ 0 , 2 , 4 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1156 */{ 10 , 1 , 24 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
-1157 */{ 0 , 2 , 12 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1158 */{ 0 , 2 , 1 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1159 */{ 6 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1160 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1161 */{ 0 , 1 , 28 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1162 */{ 2 , 1 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1163 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1164 */{ 11 , 1 , 26 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1165 */{ 0 , 2 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1166 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1167 */{ 7 , 1 , 23 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1168 */{ 0 , 2 , 11 , 37488 },/* 30 29 29 30 29 29 30 29 29 30 30 30 0 354
-1169 */{ 0 , 1 , 30 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1170 */{ 5 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1171 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1172 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1173 */{ 1 , 1 , 16 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1174 */{ 0 , 2 , 4 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
-1175 */{ 9 , 1 , 25 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
-1176 */{ 0 , 2 , 12 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1177 */{ 0 , 2 , 1 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1178 */{ 6 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1179 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1180 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1181 */{ 3 , 1 , 17 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1182 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1183 */{ 11 , 1 , 26 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1184 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1185 */{ 0 , 2 , 2 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1186 */{ 7 , 1 , 23 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1187 */{ 0 , 2 , 10 , 53392 },/* 30 30 29 30 29 29 30 29 29 30 30 0 0 325
-1188 */{ 0 , 1 , 1 , 29848 },/* 29 30 30 30 29 30 29 29 30 29 29 30 30 384
-1189 */{ 5 , 1 , 19 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1190 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1191 */{ 0 , 1 , 27 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
-1192 */{ 2 , 1 , 17 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1193 */{ 0 , 2 , 4 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1194 */{ 10 , 1 , 24 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1195 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1196 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1197 */{ 6 , 1 , 20 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1198 */{ 0 , 2 , 8 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1199 */{ 0 , 1 , 28 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1200 */{ 2 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1201 */{ 0 , 2 , 5 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1202 */{ 12 , 1 , 26 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
-1203 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1204 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1205 */{ 8 , 1 , 22 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
-1206 */{ 0 , 2 , 10 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1207 */{ 0 , 1 , 30 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1208 */{ 4 , 1 , 19 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
-1209 */{ 0 , 2 , 6 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1210 */{ 0 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1211 */{ 2 , 1 , 17 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1212 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1213 */{ 9 , 1 , 24 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1214 */{ 0 , 2 , 12 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
-1215 */{ 0 , 2 , 1 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1216 */{ 7 , 1 , 21 , 27944 },/* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
-1217 */{ 0 , 2 , 8 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1218 */{ 0 , 1 , 28 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1219 */{ 3 , 1 , 18 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1220 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1221 */{ 12 , 1 , 25 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1222 */{ 0 , 2 , 13 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1223 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1224 */{ 8 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1225 */{ 0 , 2 , 9 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1226 */{ 0 , 1 , 30 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1227 */{ 5 , 1 , 19 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1228 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1229 */{ 0 , 1 , 27 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1230 */{ 2 , 1 , 16 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1231 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1232 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1233 */{ 0 , 2 , 11 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1234 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1235 */{ 7 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1236 */{ 0 , 2 , 9 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1237 */{ 0 , 1 , 28 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1238 */{ 4 , 1 , 18 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1239 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1240 */{ 12 , 1 , 26 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
-1241 */{ 0 , 2 , 13 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1242 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1243 */{ 8 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1244 */{ 0 , 2 , 10 , 44624 },/* 30 29 30 29 30 30 30 29 29 30 29 30 0 355
-1245 */{ 0 , 1 , 30 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1246 */{ 4 , 1 , 19 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1247 */{ 0 , 2 , 7 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1248 */{ 0 , 1 , 28 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1249 */{ 2 , 1 , 16 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1250 */{ 0 , 2 , 3 , 58672 },/* 30 30 30 29 29 30 29 30 29 29 30 30 0 355
-1251 */{ 10 , 1 , 24 , 27800 },/* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
-1252 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1253 */{ 0 , 1 , 31 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1254 */{ 6 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1255 */{ 0 , 2 , 9 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1256 */{ 0 , 1 , 29 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1257 */{ 4 , 1 , 17 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1258 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1259 */{ 11 , 1 , 25 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1260 */{ 0 , 2 , 13 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1261 */{ 0 , 2 , 1 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-1262 */{ 9 , 1 , 22 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1263 */{ 0 , 2 , 10 , 21872 },/* 29 30 29 30 29 30 29 30 29 30 30 30 0 355
-1264 */{ 0 , 1 , 31 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
-1265 */{ 5 , 1 , 19 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1266 */{ 0 , 2 , 7 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1267 */{ 0 , 1 , 27 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1268 */{ 1 , 1 , 16 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1269 */{ 0 , 2 , 3 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1270 */{ 11 , 1 , 23 , 46528 },/* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
-1271 */{ 0 , 2 , 11 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1272 */{ 0 , 2 , 1 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1273 */{ 6 , 1 , 21 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1274 */{ 0 , 2 , 9 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1275 */{ 0 , 1 , 29 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1276 */{ 3 , 1 , 18 , 27224 },/* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
-1277 */{ 0 , 2 , 5 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1278 */{ 11 , 1 , 25 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1279 */{ 0 , 2 , 13 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1280 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1281 */{ 8 , 1 , 22 , 10984 },/* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
-1282 */{ 0 , 2 , 10 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
-1283 */{ 0 , 1 , 30 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1284 */{ 5 , 1 , 19 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1285 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
-1286 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1287 */{ 2 , 1 , 15 , 62096 },/* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
-1288 */{ 0 , 2 , 3 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-1289 */{ 10 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1290 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1291 */{ 0 , 2 , 1 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1292 */{ 6 , 1 , 21 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1293 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1294 */{ 0 , 1 , 28 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1295 */{ 4 , 1 , 17 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1296 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1297 */{ 12 , 1 , 24 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
-1298 */{ 0 , 2 , 12 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1299 */{ 0 , 2 , 2 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1300 */{ 8 , 1 , 23 , 2424 },/* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
-1301 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1302 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1303 */{ 5 , 1 , 19 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1304 */{ 0 , 2 , 6 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1305 */{ 0 , 1 , 26 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1306 */{ 1 , 1 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1307 */{ 0 , 2 , 3 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
-1308 */{ 11 , 1 , 24 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1309 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1310 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1311 */{ 7 , 1 , 20 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1312 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1313 */{ 0 , 1 , 27 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1314 */{ 3 , 1 , 17 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1315 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1316 */{ 0 , 1 , 25 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1317 */{ 1 , 1 , 14 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1318 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1319 */{ 8 , 1 , 22 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
-1320 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1321 */{ 0 , 1 , 29 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1322 */{ 5 , 1 , 18 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1323 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1324 */{ 0 , 1 , 27 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1325 */{ 1 , 1 , 15 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1326 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1327 */{ 9 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1328 */{ 0 , 2 , 12 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1329 */{ 0 , 1 , 31 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1330 */{ 7 , 1 , 20 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1331 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1332 */{ 0 , 1 , 28 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1333 */{ 3 , 1 , 17 , 19368 },/* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
-1334 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1335 */{ 12 , 1 , 25 , 42608 },/* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
-1336 */{ 0 , 2 , 13 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
-1337 */{ 0 , 2 , 1 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
-1338 */{ 8 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1339 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1340 */{ 0 , 1 , 29 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1341 */{ 5 , 1 , 18 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1342 */{ 0 , 2 , 6 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1343 */{ 0 , 1 , 27 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1344 */{ 2 , 1 , 16 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
-1345 */{ 0 , 2 , 3 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
-1346 */{ 10 , 1 , 23 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1347 */{ 0 , 2 , 11 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1348 */{ 0 , 1 , 31 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1349 */{ 7 , 1 , 19 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
-1350 */{ 0 , 2 , 7 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1351 */{ 0 , 1 , 28 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1352 */{ 3 , 1 , 18 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
-1353 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1354 */{ 0 , 1 , 25 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1355 */{ 1 , 1 , 14 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1356 */{ 0 , 2 , 2 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1357 */{ 9 , 1 , 21 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1358 */{ 0 , 2 , 9 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
-1359 */{ 0 , 1 , 29 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
-1360 */{ 5 , 1 , 19 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1361 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1362 */{ 0 , 1 , 27 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1363 */{ 3 , 1 , 16 , 41656 },/* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
-1364 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1365 */{ 10 , 1 , 23 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
-1366 */{ 0 , 2 , 10 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1367 */{ 0 , 1 , 31 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1368 */{ 7 , 1 , 20 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1369 */{ 0 , 2 , 7 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
-1370 */{ 0 , 1 , 28 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
-1371 */{ 3 , 1 , 17 , 50544 },/* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
-1372 */{ 0 , 2 , 5 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1373 */{ 11 , 1 , 24 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1374 */{ 0 , 2 , 12 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1375 */{ 0 , 2 , 1 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1376 */{ 9 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1377 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1378 */{ 0 , 1 , 29 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1379 */{ 5 , 1 , 19 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-1380 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1381 */{ 0 , 1 , 26 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
-1382 */{ 2 , 1 , 15 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1383 */{ 0 , 2 , 3 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1384 */{ 10 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1385 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1386 */{ 0 , 1 , 31 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1387 */{ 6 , 1 , 20 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1388 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1389 */{ 0 , 1 , 28 , 20912 },/* 29 30 29 30 29 29 29 30 30 29 30 30 0 354
-1390 */{ 4 , 1 , 17 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1391 */{ 0 , 2 , 5 , 25904 },/* 29 30 30 29 29 30 29 30 29 29 30 30 0 354
-1392 */{ 12 , 1 , 25 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1393 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1394 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1395 */{ 9 , 1 , 22 , 11176 },/* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
-1396 */{ 0 , 2 , 10 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1397 */{ 0 , 1 , 29 , 50032 },/* 30 30 29 29 29 29 30 30 29 30 30 30 0 355
-1398 */{ 5 , 1 , 19 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1399 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1400 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1401 */{ 3 , 1 , 15 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1402 */{ 0 , 2 , 2 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1403 */{ 11 , 1 , 23 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1404 */{ 0 , 2 , 11 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1405 */{ 0 , 1 , 31 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1406 */{ 7 , 1 , 20 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
-1407 */{ 0 , 2 , 8 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
-1408 */{ 0 , 1 , 28 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
-1409 */{ 4 , 1 , 16 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1410 */{ 0 , 2 , 4 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1411 */{ 12 , 1 , 24 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
-1412 */{ 0 , 2 , 12 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1413 */{ 0 , 2 , 1 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1414 */{ 9 , 1 , 22 , 9688 },/* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
-1415 */{ 0 , 2 , 10 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1416 */{ 0 , 1 , 30 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1417 */{ 5 , 1 , 18 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1418 */{ 0 , 2 , 6 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1419 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1420 */{ 1 , 1 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1421 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1422 */{ 12 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1423 */{ 0 , 2 , 11 , 19312 },/* 29 30 29 29 30 29 30 30 29 30 30 30 0 355
-1424 */{ 0 , 2 , 1 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1425 */{ 7 , 1 , 20 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1426 */{ 0 , 2 , 8 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1427 */{ 0 , 1 , 28 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1428 */{ 4 , 1 , 17 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1429 */{ 0 , 2 , 4 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1430 */{ 12 , 1 , 24 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
-1431 */{ 0 , 2 , 12 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
-1432 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1433 */{ 8 , 1 , 21 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1434 */{ 0 , 2 , 9 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1435 */{ 0 , 1 , 29 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1436 */{ 6 , 1 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1437 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1438 */{ 0 , 1 , 26 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1439 */{ 2 , 1 , 15 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-1440 */{ 0 , 2 , 3 , 38368 },/* 30 29 29 30 29 30 29 30 30 30 30 29 0 355
-1441 */{ 11 , 1 , 23 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1442 */{ 0 , 2 , 11 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1443 */{ 0 , 1 , 31 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1444 */{ 7 , 1 , 20 , 53872 },/* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
-1445 */{ 0 , 2 , 7 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1446 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1447 */{ 4 , 1 , 17 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1448 */{ 0 , 2 , 5 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1449 */{ 0 , 1 , 24 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1450 */{ 1 , 1 , 14 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1451 */{ 0 , 2 , 2 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1452 */{ 9 , 1 , 22 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1453 */{ 0 , 2 , 9 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1454 */{ 0 , 1 , 29 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1455 */{ 6 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1456 */{ 0 , 2 , 6 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1457 */{ 0 , 1 , 26 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1458 */{ 2 , 1 , 15 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1459 */{ 0 , 2 , 3 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1460 */{ 11 , 1 , 24 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1461 */{ 0 , 2 , 10 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1462 */{ 0 , 1 , 30 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
-1463 */{ 7 , 1 , 20 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1464 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1465 */{ 0 , 1 , 27 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1466 */{ 3 , 1 , 17 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1467 */{ 0 , 2 , 5 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1468 */{ 0 , 1 , 25 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1469 */{ 2 , 1 , 13 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1470 */{ 0 , 2 , 1 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1471 */{ 9 , 1 , 21 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1472 */{ 0 , 2 , 9 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1473 */{ 0 , 1 , 28 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1474 */{ 6 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1475 */{ 0 , 2 , 6 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1476 */{ 0 , 1 , 27 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1477 */{ 2 , 1 , 15 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1478 */{ 0 , 2 , 3 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1479 */{ 10 , 1 , 23 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1480 */{ 0 , 2 , 11 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1481 */{ 0 , 1 , 30 , 29856 },/* 29 30 30 30 29 30 29 29 30 29 30 29 0 354
-1482 */{ 8 , 1 , 19 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1483 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1484 */{ 0 , 1 , 28 , 21424 },/* 29 30 29 30 29 29 30 30 30 29 30 30 0 355
-1485 */{ 4 , 1 , 17 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1486 */{ 0 , 2 , 5 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1487 */{ 0 , 1 , 25 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1488 */{ 1 , 1 , 14 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1489 */{ 0 , 2 , 1 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1490 */{ 9 , 1 , 21 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1491 */{ 0 , 2 , 9 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1492 */{ 0 , 1 , 29 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1493 */{ 5 , 1 , 18 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1494 */{ 0 , 2 , 6 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1495 */{ 0 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1496 */{ 3 , 1 , 16 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1497 */{ 0 , 2 , 2 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1498 */{ 11 , 1 , 22 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
-1499 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1500 */{ 0 , 1 , 31 , 5792 },/* 29 29 29 30 29 30 30 29 30 29 30 29 0 353
-1501 */{ 7 , 1 , 19 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1502 */{ 0 , 2 , 7 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1503 */{ 0 , 1 , 28 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1504 */{ 4 , 1 , 17 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1505 */{ 0 , 2 , 4 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1506 */{ 0 , 1 , 24 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1507 */{ 1 , 1 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
-1508 */{ 0 , 2 , 1 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1509 */{ 9 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1510 */{ 0 , 2 , 9 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1511 */{ 0 , 1 , 29 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1512 */{ 5 , 1 , 19 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1513 */{ 0 , 2 , 6 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1514 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1515 */{ 4 , 1 , 15 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1516 */{ 0 , 2 , 3 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1517 */{ 12 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1518 */{ 0 , 2 , 10 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
-1519 */{ 0 , 1 , 31 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1520 */{ 8 , 1 , 20 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1521 */{ 0 , 2 , 7 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 0 355
-1522 */{ 0 , 1 , 28 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1523 */{ 4 , 1 , 17 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1524 */{ 0 , 2 , 4 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1525 */{ 12 , 1 , 23 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
-1526 */{ 0 , 2 , 11 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 0 355
-1527 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1528 */{ 10 , 1 , 22 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1529 */{ 0 , 2 , 9 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1530 */{ 0 , 1 , 29 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
-1531 */{ 6 , 1 , 18 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1532 */{ 0 , 2 , 6 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1533 */{ 0 , 1 , 25 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1534 */{ 2 , 1 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1535 */{ 0 , 2 , 2 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 0 355
-1536 */{ 12 , 1 , 23 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1537 */{ 0 , 2 , 10 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1538 */{ 0 , 1 , 31 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1539 */{ 7 , 1 , 20 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1540 */{ 0 , 2 , 8 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1541 */{ 0 , 1 , 27 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1542 */{ 5 , 1 , 16 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1543 */{ 0 , 2 , 4 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
-1544 */{ 0 , 1 , 24 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1545 */{ 1 , 1 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1546 */{ 0 , 2 , 1 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-1547 */{ 9 , 1 , 22 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1548 */{ 0 , 2 , 10 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1549 */{ 0 , 1 , 29 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1550 */{ 6 , 1 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1551 */{ 0 , 2 , 5 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1552 */{ 0 , 1 , 26 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1553 */{ 3 , 1 , 14 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1554 */{ 0 , 2 , 2 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1555 */{ 11 , 1 , 23 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1556 */{ 0 , 2 , 11 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1557 */{ 0 , 1 , 30 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1558 */{ 7 , 1 , 20 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1559 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1560 */{ 0 , 1 , 27 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1561 */{ 5 , 1 , 16 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1562 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1563 */{ 0 , 1 , 24 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1564 */{ 2 , 1 , 14 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1565 */{ 0 , 2 , 1 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1566 */{ 10 , 1 , 21 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1567 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1568 */{ 0 , 1 , 29 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1569 */{ 6 , 1 , 17 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1570 */{ 0 , 2 , 5 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1571 */{ 0 , 1 , 26 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
-1572 */{ 2 , 1 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1573 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1574 */{ 12 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1575 */{ 0 , 2 , 11 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1576 */{ 0 , 1 , 31 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1577 */{ 8 , 1 , 19 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1578 */{ 0 , 2 , 7 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1579 */{ 0 , 1 , 27 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1580 */{ 4 , 1 , 16 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1581 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1582 */{ 0 , 1 , 24 , 39024 },/* 30 29 29 30 29 29 30 30 39 30 30 30 0 365
-1583 */{ 2 , 1 , 24 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1584 */{ 0 , 2 , 12 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1585 */{ 9 , 1 , 31 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1586 */{ 0 , 2 , 18 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1587 */{ 0 , 3 , 9 , 53968 },/* 30 30 29 30 29 30 29 29 30 29 30 0 0 325
-1588 */{ 6 , 1 , 28 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
-1589 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1590 */{ 0 , 2 , 5 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1591 */{ 3 , 1 , 25 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
-1592 */{ 0 , 2 , 13 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1593 */{ 11 , 2 , 1 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1594 */{ 0 , 2 , 20 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1595 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1596 */{ 8 , 1 , 29 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1597 */{ 0 , 2 , 16 , 46288 },/* 30 29 30 30 29 30 29 29 30 30 29 30 0 355
-1598 */{ 0 , 2 , 6 , 22192 },/* 29 30 29 30 29 30 30 29 30 29 30 30 0 355
-1599 */{ 4 , 1 , 27 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
-1600 */{ 0 , 2 , 15 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1601 */{ 0 , 2 , 3 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1602 */{ 2 , 1 , 23 , 51608 },/* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
-1603 */{ 0 , 2 , 11 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1604 */{ 9 , 1 , 31 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1605 */{ 0 , 2 , 18 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1606 */{ 0 , 2 , 7 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1607 */{ 6 , 1 , 28 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1608 */{ 0 , 2 , 16 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-1609 */{ 0 , 2 , 5 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-1610 */{ 3 , 1 , 25 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1611 */{ 0 , 2 , 13 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1612 */{ 11 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1613 */{ 0 , 2 , 19 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1614 */{ 0 , 2 , 9 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1615 */{ 8 , 1 , 29 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1616 */{ 0 , 2 , 17 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
-1617 */{ 0 , 2 , 6 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1618 */{ 4 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1619 */{ 0 , 2 , 14 , 42224 },/* 30 29 30 29 29 30 29 29 30 30 30 30 0 355
-1620 */{ 0 , 2 , 4 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
-1621 */{ 2 , 1 , 22 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1622 */{ 0 , 2 , 10 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1623 */{ 10 , 1 , 31 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1624 */{ 0 , 2 , 19 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1625 */{ 0 , 2 , 7 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1626 */{ 6 , 1 , 28 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1627 */{ 0 , 2 , 16 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
-1628 */{ 0 , 2 , 5 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1629 */{ 4 , 1 , 24 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1630 */{ 0 , 2 , 12 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1631 */{ 11 , 2 , 1 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1632 */{ 0 , 2 , 20 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1633 */{ 0 , 2 , 8 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-1634 */{ 8 , 1 , 29 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1635 */{ 0 , 2 , 17 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1636 */{ 0 , 2 , 7 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1637 */{ 4 , 1 , 26 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1638 */{ 0 , 2 , 14 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1639 */{ 0 , 2 , 3 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1640 */{ 1 , 1 , 23 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1641 */{ 0 , 2 , 10 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1642 */{ 11 , 1 , 30 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1643 */{ 0 , 2 , 19 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1644 */{ 0 , 2 , 8 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1645 */{ 6 , 1 , 28 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1646 */{ 0 , 2 , 16 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1647 */{ 0 , 2 , 5 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1648 */{ 3 , 1 , 24 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1649 */{ 0 , 2 , 11 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1650 */{ 11 , 2 , 1 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
-1651 */{ 0 , 2 , 20 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1652 */{ 0 , 2 , 10 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
-1653 */{ 7 , 1 , 29 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
-1654 */{ 0 , 2 , 17 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1655 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1656 */{ 5 , 1 , 26 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1657 */{ 0 , 2 , 13 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1658 */{ 0 , 2 , 2 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1659 */{ 3 , 1 , 23 , 39592 },/* 30 29 29 30 30 29 30 29 30 29 30 29 30 384
-1660 */{ 0 , 2 , 11 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1661 */{ 7 , 1 , 30 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
-1662 */{ 0 , 2 , 18 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 0 355
-1663 */{ 0 , 2 , 8 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1664 */{ 6 , 1 , 28 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1665 */{ 0 , 2 , 15 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1666 */{ 0 , 2 , 4 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1667 */{ 4 , 1 , 24 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1668 */{ 0 , 2 , 12 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1669 */{ 0 , 2 , 1 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
-1670 */{ 2 , 1 , 21 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1671 */{ 0 , 2 , 9 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1672 */{ 7 , 1 , 30 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1673 */{ 0 , 2 , 17 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1674 */{ 0 , 2 , 6 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1675 */{ 5 , 1 , 26 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-1676 */{ 0 , 2 , 14 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1677 */{ 0 , 2 , 2 , 44432 },/* 30 29 30 29 30 30 29 30 30 29 29 30 0 355
-1678 */{ 3 , 1 , 23 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-1679 */{ 0 , 2 , 11 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1680 */{ 8 , 1 , 31 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1681 */{ 0 , 2 , 18 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1682 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1683 */{ 6 , 1 , 27 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1684 */{ 0 , 2 , 15 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-1685 */{ 0 , 2 , 3 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1686 */{ 4 , 1 , 24 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-1687 */{ 0 , 2 , 12 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1688 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1689 */{ 3 , 1 , 21 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1690 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1691 */{ 7 , 1 , 29 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1692 */{ 0 , 2 , 17 , 45136 },/* 30 29 29 32 29 29 29 29 29 30 29 30 0 354
-1693 */{ 0 , 2 , 5 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-1694 */{ 5 , 1 , 25 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
-1695 */{ 0 , 2 , 13 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-1696 */{ 0 , 2 , 3 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1697 */{ 3 , 1 , 23 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1698 */{ 0 , 2 , 11 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
-1699 */{ 7 , 1 , 31 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1700 */{ 0 , 2 , 19 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1701 */{ 0 , 2 , 8 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1702 */{ 6 , 1 , 28 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1703 */{ 0 , 2 , 16 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-1704 */{ 0 , 2 , 5 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1705 */{ 4 , 1 , 25 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1706 */{ 0 , 2 , 13 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1707 */{ 0 , 2 , 3 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1708 */{ 3 , 1 , 23 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1709 */{ 0 , 2 , 10 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1710 */{ 7 , 1 , 30 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1711 */{ 0 , 2 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1712 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1713 */{ 5 , 1 , 26 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1714 */{ 0 , 2 , 14 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
-1715 */{ 0 , 2 , 4 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1716 */{ 3 , 1 , 24 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1717 */{ 0 , 2 , 11 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1718 */{ 8 , 1 , 31 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1719 */{ 0 , 2 , 19 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1720 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1721 */{ 6 , 1 , 28 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1722 */{ 0 , 2 , 16 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1723 */{ 0 , 2 , 5 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1724 */{ 4 , 1 , 26 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-1725 */{ 0 , 2 , 13 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
-1726 */{ 0 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1727 */{ 3 , 1 , 22 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-1728 */{ 0 , 2 , 10 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1729 */{ 7 , 1 , 29 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1730 */{ 0 , 2 , 17 , 40272 },/* 30 29 29 30 30 30 29 30 29 30 29 30 0 355
-1731 */{ 0 , 2 , 7 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
-1732 */{ 5 , 1 , 27 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1733 */{ 0 , 2 , 14 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1734 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1735 */{ 4 , 1 , 24 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1736 */{ 0 , 2 , 12 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1737 */{ 9 , 1 , 31 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1738 */{ 0 , 2 , 19 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1739 */{ 0 , 2 , 8 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1740 */{ 6 , 1 , 29 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-1741 */{ 0 , 2 , 16 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1742 */{ 0 , 2 , 5 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1743 */{ 4 , 1 , 26 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1744 */{ 0 , 2 , 13 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
-1745 */{ 0 , 2 , 1 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 0 355
-1746 */{ 3 , 1 , 22 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1747 */{ 0 , 2 , 9 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1748 */{ 7 , 1 , 30 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1749 */{ 0 , 2 , 17 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1750 */{ 0 , 2 , 7 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1751 */{ 5 , 1 , 27 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1752 */{ 0 , 2 , 15 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
-1753 */{ 0 , 2 , 3 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1754 */{ 4 , 2 , 22 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1755 */{ 0 , 2 , 11 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1756 */{ 9 , 1 , 31 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
-1757 */{ 0 , 2 , 18 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1758 */{ 0 , 2 , 8 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1759 */{ 6 , 1 , 29 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-1760 */{ 0 , 2 , 17 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1761 */{ 0 , 2 , 5 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1762 */{ 5 , 1 , 25 , 45400 },/* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
-1763 */{ 0 , 2 , 13 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1764 */{ 0 , 2 , 2 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1765 */{ 2 , 1 , 21 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
-1766 */{ 0 , 2 , 9 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
-1767 */{ 7 , 1 , 30 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1768 */{ 0 , 2 , 18 , 21360 },/* 29 30 29 30 29 29 30 30 29 30 30 30 0 355
-1769 */{ 0 , 2 , 7 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1770 */{ 5 , 1 , 27 , 25272 },/* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
-1771 */{ 0 , 2 , 15 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1772 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1773 */{ 3 , 1 , 23 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1774 */{ 0 , 2 , 11 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1775 */{ 10 , 1 , 31 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1776 */{ 0 , 2 , 19 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1777 */{ 0 , 2 , 8 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1778 */{ 6 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1779 */{ 0 , 2 , 16 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1780 */{ 0 , 2 , 5 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1781 */{ 5 , 1 , 24 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1782 */{ 0 , 2 , 12 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1783 */{ 0 , 2 , 2 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1784 */{ 3 , 1 , 22 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1785 */{ 0 , 2 , 9 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1786 */{ 7 , 1 , 30 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1787 */{ 0 , 2 , 18 , 19120 },/* 29 30 29 29 30 29 30 29 30 29 30 30 0 354
-1788 */{ 0 , 2 , 7 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
-1789 */{ 5 , 1 , 26 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1790 */{ 0 , 2 , 14 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1791 */{ 0 , 2 , 3 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1792 */{ 4 , 1 , 24 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1793 */{ 0 , 2 , 11 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1794 */{ 0 , 1 , 31 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1795 */{ 2 , 1 , 21 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1796 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1797 */{ 6 , 1 , 28 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1798 */{ 0 , 2 , 16 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1799 */{ 0 , 2 , 5 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1800 */{ 4 , 1 , 25 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1801 */{ 0 , 2 , 13 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1802 */{ 0 , 2 , 3 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
-1803 */{ 2 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1804 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1805 */{ 6 , 1 , 31 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1806 */{ 0 , 2 , 18 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
-1807 */{ 0 , 2 , 7 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
-1808 */{ 5 , 1 , 28 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1809 */{ 0 , 2 , 14 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
-1810 */{ 0 , 2 , 4 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
-1811 */{ 3 , 1 , 25 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1812 */{ 0 , 2 , 13 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1813 */{ 0 , 2 , 1 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
-1814 */{ 2 , 1 , 21 , 53608 },/* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
-1815 */{ 0 , 2 , 9 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1816 */{ 6 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1817 */{ 0 , 2 , 16 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1818 */{ 0 , 2 , 5 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1819 */{ 4 , 1 , 26 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1820 */{ 0 , 2 , 14 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1821 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1822 */{ 3 , 1 , 23 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
-1823 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1824 */{ 7 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1825 */{ 0 , 2 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1826 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1827 */{ 5 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1828 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1829 */{ 0 , 2 , 4 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1830 */{ 4 , 1 , 25 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1831 */{ 0 , 2 , 13 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1832 */{ 9 , 2 , 2 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1833 */{ 0 , 2 , 20 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1834 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1835 */{ 6 , 1 , 29 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1836 */{ 0 , 2 , 17 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1837 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1838 */{ 4 , 1 , 26 , 21352 },/* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
-1839 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1840 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1841 */{ 3 , 1 , 23 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
-1842 */{ 0 , 2 , 10 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1843 */{ 7 , 1 , 30 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1844 */{ 0 , 2 , 18 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1845 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1846 */{ 5 , 1 , 27 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-1847 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1848 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1849 */{ 4 , 1 , 24 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
-1850 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1851 */{ 8 , 2 , 1 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1852 */{ 0 , 2 , 20 , 45712 },/* 30 29 30 30 29 29 30 29 30 29 29 30 0 354
-1853 */{ 0 , 2 , 8 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1854 */{ 7 , 1 , 29 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1855 */{ 0 , 2 , 17 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1856 */{ 0 , 2 , 6 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1857 */{ 5 , 1 , 26 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1858 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1859 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1860 */{ 3 , 1 , 23 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1861 */{ 0 , 2 , 10 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1862 */{ 8 , 1 , 30 , 44360 },/* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
-1863 */{ 0 , 2 , 18 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1864 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1865 */{ 5 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1866 */{ 0 , 2 , 15 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1867 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1868 */{ 4 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1869 */{ 0 , 2 , 11 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
-1870 */{ 10 , 1 , 31 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
-1871 */{ 0 , 2 , 19 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
-1872 */{ 0 , 2 , 9 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1873 */{ 6 , 1 , 29 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1874 */{ 0 , 2 , 17 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1875 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1876 */{ 5 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1877 */{ 0 , 2 , 13 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1878 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1879 */{ 3 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1880 */{ 0 , 2 , 10 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1881 */{ 7 , 1 , 30 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1882 */{ 0 , 2 , 18 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1883 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1884 */{ 5 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1885 */{ 0 , 2 , 15 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1886 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1887 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1888 */{ 0 , 2 , 12 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1889 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1890 */{ 2 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1891 */{ 0 , 2 , 9 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1892 */{ 6 , 1 , 30 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1893 */{ 0 , 2 , 17 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1894 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1895 */{ 5 , 1 , 26 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1896 */{ 0 , 2 , 13 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1897 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1898 */{ 3 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1899 */{ 0 , 2 , 10 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1900 */{ 8 , 1 , 31 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1914 */{ 5 , 1 , 26 , 55624 },/* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
-1915 */{ 0 , 2 , 14 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1916 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */{ 0 , 2 , 11 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1919 */{ 7 , 2 , 1 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1920 */{ 0 , 2 , 20 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */{ 0 , 2 , 16 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1924 */{ 0 , 2 , 5 , 44352 },/* 30 29 30 29 30 30 29 30 29 30 29 29 0 354
-1925 */{ 4 , 1 , 24 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1927 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1928 */{ 2 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */{ 0 , 2 , 17 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
-1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */{ 0 , 2 , 14 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
-1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1936 */{ 3 , 1 , 24 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */{ 0 , 2 , 15 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1943 */{ 0 , 2 , 5 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1944 */{ 4 , 1 , 26 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1949 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1950 */{ 0 , 2 , 17 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1952 */{ 5 , 1 , 27 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1953 */{ 0 , 2 , 14 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
-1954 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-1955 */{ 3 , 1 , 24 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1957 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1958 */{ 0 , 2 , 19 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
-2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
-2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
-2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
-2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-2050 */{ 3 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
- */};
-
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+0918 */ { 00, 02, 19, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+0919 */ { 00, 02, 09, 0b0100010111010000 }, /* 29 30 29 29 29 30 29 30 30 30 29 30 354
+0920 */ { 06, 01, 29, 0b1010001011011000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+0921 */ { 00, 02, 16, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+0922 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+0923 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+0924 */ { 00, 02, 13, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
+0925 */ { 12, 02, 01, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+0926 */ { 00, 02, 20, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+0927 */ { 00, 02, 10, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+0928 */ { 08, 01, 31, 0b0100010110111000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
+0929 */ { 00, 02, 18, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+0930 */ { 00, 02, 07, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+0931 */ { 05, 01, 27, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
+0932 */ { 00, 02, 14, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+0933 */ { 00, 02, 03, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+0934 */ { 01, 01, 23, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+0935 */ { 00, 02, 11, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+0936 */ { 11, 02, 01, 0b0101001101100000 }, /* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
+0937 */ { 00, 02, 18, 0b1100101011000000 }, /* 30 30 29 29 30 29 30 29 30 30 29 29 354
+0938 */ { 00, 02, 07, 0b1110010101100000 }, /* 30 30 30 29 29 30 29 30 29 30 30 29 355
+0939 */ { 07, 01, 28, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+0940 */ { 00, 02, 16, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+0941 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+0942 */ { 03, 01, 25, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+0943 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+0944 */ { 12, 02, 02, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+0945 */ { 00, 02, 20, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+0946 */ { 00, 02, 10, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+0947 */ { 07, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+0948 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+0949 */ { 00, 02, 06, 0b1011001001100000 }, /* 30 29 30 30 29 29 30 29 29 30 30 29 354
+0950 */ { 05, 01, 26, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+0951 */ { 00, 02, 14, 0b1011001101110000 }, /* 30 29 30 30 29 29 30 30 29 30 30 30 356
+0953 */ { 00, 01, 05, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 355
+0953 */ { 01, 01, 23, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+0954 */ { 00, 02, 11, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+0955 */ { 09, 02, 01, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+0956 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+0957 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+0958 */ { 07, 01, 28, 0b1010101010011000 }, /* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
+0959 */ { 00, 02, 16, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+0960 */ { 00, 02, 05, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+0961 */ { 03, 01, 25, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+0962 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+0963 */ { 12, 02, 02, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+0964 */ { 00, 02, 21, 0b1010001101110000 }, /* 30 29 30 29 29 29 30 30 29 30 30 30 355
+0965 */ { 00, 02, 10, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 354
+0966 */ { 08, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+0967 */ { 00, 02, 17, 0b1101010010110000 }, /* 30 30 29 30 29 30 29 29 30 29 30 30 355
+0968 */ { 00, 02, 07, 0b0101101010010000 }, /* 29 30 29 30 30 29 30 29 30 29 29 30 354
+0969 */ { 05, 01, 26, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+0970 */ { 00, 02, 14, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+0971 */ { 00, 02, 04, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+0972 */ { 02, 01, 24, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+0973 */ { 00, 02, 11, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
+0974 */ { 10, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+0975 */ { 00, 02, 19, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+0976 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+0977 */ { 07, 01, 27, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
+0978 */ { 00, 02, 15, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+0979 */ { 00, 02, 05, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+0980 */ { 03, 01, 26, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+0981 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+0982 */ { 12, 02, 02, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+0983 */ { 00, 02, 21, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+0984 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+0985 */ { 09, 01, 29, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+0986 */ { 00, 02, 17, 0b1010110010100000 }, /* 30 29 30 29 30 30 29 29 30 29 30 29 354
+0987 */ { 00, 02, 06, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+0988 */ { 05, 01, 27, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+0989 */ { 00, 02, 14, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+0990 */ { 00, 02, 04, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+0991 */ { 02, 01, 24, 0b1001001010111000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+0992 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+0993 */ { 10, 01, 31, 0b0110100101011000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
+0994 */ { 00, 02, 19, 0b0101100101010000 }, /* 29 30 29 30 30 29 29 30 29 30 29 30 354
+0995 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+0996 */ { 07, 01, 28, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+0997 */ { 00, 02, 15, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+0998 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+0999 */ { 03, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1000 */ { 00, 02, 13, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1001 */ { 12, 02, 03, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1002 */ { 00, 02, 21, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1003 */ { 00, 02, 10, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1004 */ { 09, 01, 31, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1005 */ { 00, 02, 18, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1006 */ { 00, 02, 07, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1007 */ { 05, 01, 28, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1008 */ { 00, 02, 16, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+1009 */ { 00, 02, 04, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1010 */ { 02, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1011 */ { 00, 02, 12, 0b1011001001100000 }, /* 30 29 30 30 29 29 30 29 29 30 30 29 354
+1012 */ { 10, 02, 01, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1013 */ { 00, 02, 19, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1014 */ { 00, 02, 09, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
+1015 */ { 06, 01, 29, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1016 */ { 00, 02, 17, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1017 */ { 00, 02, 06, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1018 */ { 04, 01, 26, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1019 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1020 */ { 12, 02, 03, 0b1010101001011000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1021 */ { 00, 02, 21, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1022 */ { 00, 02, 10, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1023 */ { 09, 01, 31, 0b0010110110101000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
+1024 */ { 00, 02, 19, 0b0010101101010000 }, /* 29 29 30 29 30 29 30 30 29 30 29 30 354
+1025 */ { 00, 02, 07, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
+1026 */ { 05, 01, 28, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1027 */ { 00, 02, 15, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 355
+1028 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1029 */ { 02, 01, 24, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1030 */ { 00, 02, 11, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
+1031 */ { 10, 02, 01, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1032 */ { 00, 02, 20, 0b0110011011010000 }, /* 29 30 30 29 29 30 30 29 30 30 29 30 355
+1033 */ { 00, 02, 09, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1034 */ { 06, 01, 29, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1035 */ { 00, 02, 17, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1036 */ { 00, 02, 06, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1037 */ { 04, 01, 25, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1038 */ { 00, 02, 13, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1039 */ { 12, 02, 02, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1040 */ { 00, 02, 21, 0b1011010110000000 }, /* 30 29 30 30 29 30 29 30 30 29 29 29 354
+1041 */ { 00, 02, 09, 0b1101011010110000 }, /* 30 30 29 30 29 30 30 29 30 29 30 30 356
+1042 */ { 09, 01, 31, 0b0010011011011000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1043 */ { 00, 02, 19, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1044 */ { 00, 02, 08, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1045 */ { 05, 01, 27, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1046 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1047 */ { 00, 02, 04, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1048 */ { 01, 01, 24, 0b1011010101011000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
+1049 */ { 00, 02, 12, 0b0010110101010000 }, /* 29 29 30 29 30 30 29 30 29 30 29 30 354
+1050 */ { 11, 02, 01, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1051 */ { 00, 02, 20, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+1052 */ { 00, 02, 10, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+1053 */ { 07, 01, 29, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1054 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1055 */ { 00, 02, 06, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1056 */ { 03, 01, 26, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1057 */ { 00, 02, 13, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1058 */ { 12, 02, 02, 0b1010101101011000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
+1059 */ { 00, 02, 22, 0b0010011101010000 }, /* 29 29 30 29 29 30 30 30 29 30 29 30 354
+1060 */ { 00, 02, 11, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1061 */ { 08, 01, 30, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1062 */ { 00, 02, 18, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1063 */ { 00, 02, 07, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1064 */ { 05, 01, 27, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1065 */ { 00, 02, 14, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1066 */ { 00, 02, 04, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1067 */ { 01, 01, 24, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1068 */ { 00, 02, 12, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1069 */ { 11, 02, 01, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1070 */ { 00, 02, 20, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
+1071 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1072 */ { 07, 01, 29, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1073 */ { 00, 02, 16, 0b1010101001100000 }, /* 30 29 30 29 30 29 30 29 29 30 30 29 354
+1074 */ { 00, 02, 05, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1075 */ { 04, 01, 26, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1076 */ { 00, 02, 14, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
+1077 */ { 00, 02, 02, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1078 */ { 01, 01, 23, 0b0100101110011000 }, /* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
+1079 */ { 00, 02, 11, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1080 */ { 09, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1081 */ { 00, 02, 18, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1082 */ { 00, 02, 07, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1083 */ { 06, 01, 27, 0b1011010101001000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
+1084 */ { 00, 02, 15, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1085 */ { 00, 02, 04, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1086 */ { 02, 01, 24, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1087 */ { 00, 02, 12, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1088 */ { 12, 02, 02, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1089 */ { 00, 02, 19, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 355
+1090 */ { 00, 02, 09, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1091 */ { 08, 01, 29, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1092 */ { 00, 02, 16, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1093 */ { 00, 02, 05, 0b0101101101000000 }, /* 29 30 29 30 30 29 30 30 29 30 29 29 354
+1094 */ { 04, 01, 25, 0b1010101101101000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1095 */ { 00, 02, 14, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1096 */ { 00, 02, 03, 0b1110011000010000 }, /* 30 30 30 29 29 30 30 29 29 29 29 30 354
+1097 */ { 02, 01, 22, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1098 */ { 00, 02, 10, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1099 */ { 09, 01, 30, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1100 */ { 00, 02, 18, 0b0101010010100000 }, /* 29 30 29 30 29 30 29 29 30 29 30 29 353
+1101 */ { 00, 02, 07, 0b1101011001010000 }, /* 30 30 29 30 29 30 30 29 29 30 29 30 355
+1102 */ { 06, 01, 28, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1103 */ { 00, 02, 16, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1104 */ { 00, 02, 06, 0b0010011011010000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 354
+1105 */ { 02, 01, 25, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1106 */ { 00, 02, 13, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1107 */ { 10, 02, 02, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1108 */ { 00, 02, 21, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1109 */ { 00, 02, 09, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1110 */ { 08, 01, 29, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1111 */ { 00, 02, 17, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1112 */ { 00, 02, 07, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1113 */ { 04, 01, 27, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1114 */ { 00, 02, 15, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1115 */ { 00, 02, 04, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1116 */ { 01, 01, 24, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1117 */ { 00, 02, 11, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1118 */ { 09, 01, 31, 0b0111001010101000 }, /* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
+1119 */ { 00, 02, 19, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1120 */ { 00, 02, 08, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1121 */ { 05, 01, 28, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1122 */ { 00, 02, 16, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1123 */ { 00, 02, 05, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1124 */ { 03, 01, 26, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1125 */ { 00, 02, 12, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1126 */ { 11, 02, 01, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1127 */ { 00, 02, 20, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1128 */ { 00, 02, 10, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1129 */ { 08, 01, 29, 0b1001101110010000 }, /* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
+1130 */ { 00, 02, 17, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1131 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1132 */ { 04, 01, 27, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1133 */ { 00, 02, 14, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1134 */ { 00, 02, 03, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1135 */ { 02, 01, 23, 0b1101100100101000 }, /* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+1136 */ { 00, 02, 11, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1137 */ { 10, 01, 30, 0b1101011010101000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
+1138 */ { 00, 02, 19, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1139 */ { 00, 02, 08, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1140 */ { 06, 01, 29, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1141 */ { 00, 02, 16, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1142 */ { 00, 02, 05, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1143 */ { 04, 01, 25, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1144 */ { 00, 02, 13, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1145 */ { 11, 02, 01, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1146 */ { 00, 02, 20, 0b0110101101000000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 354
+1147 */ { 00, 02, 09, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1148 */ { 08, 01, 30, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1149 */ { 00, 02, 17, 0b1001100101110000 }, /* 30 29 29 30 30 29 29 30 29 30 30 30 355
+1150 */ { 00, 02, 07, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1151 */ { 04, 01, 27, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1152 */ { 00, 02, 15, 0b0101010010110000 }, /* 29 30 29 30 29 30 29 29 30 29 30 30 354
+1153 */ { 12, 02, 03, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1154 */ { 00, 02, 21, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1155 */ { 00, 02, 11, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1156 */ { 10, 01, 31, 0b1010101101101000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1157 */ { 00, 02, 19, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1158 */ { 00, 02, 08, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1159 */ { 06, 01, 28, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1160 */ { 00, 02, 16, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1161 */ { 00, 02, 04, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1162 */ { 02, 01, 24, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1163 */ { 00, 02, 12, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1164 */ { 11, 02, 02, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1165 */ { 00, 02, 20, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1166 */ { 00, 02, 10, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1167 */ { 07, 01, 30, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1168 */ { 00, 02, 18, 0b1001001001110000 }, /* 30 29 29 30 29 29 30 29 29 30 30 30 354
+1169 */ { 00, 02, 06, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1170 */ { 05, 01, 26, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1171 */ { 00, 02, 14, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1172 */ { 00, 02, 03, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1173 */ { 01, 01, 23, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1174 */ { 00, 02, 11, 0b0100110110110000 }, /* 29 30 29 29 30 30 29 30 30 29 30 30 355
+1175 */ { 09, 02, 01, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
+1176 */ { 00, 02, 19, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1177 */ { 00, 02, 08, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1178 */ { 06, 01, 28, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1179 */ { 00, 02, 16, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1180 */ { 00, 02, 05, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1181 */ { 03, 01, 24, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1182 */ { 00, 02, 12, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1183 */ { 11, 02, 02, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1184 */ { 00, 02, 21, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1185 */ { 00, 02, 09, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1186 */ { 07, 01, 30, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1187 */ { 00, 02, 17, 0b1101000010010000 }, /* 30 30 29 30 29 29 29 29 30 29 29 30 353
+1188 */ { 00, 01, 08, 0b0111010010011000 }, /* 29 30 30 30 29 30 29 29 30 29 29 30 354
+1189 */ { 05, 01, 26, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1190 */ { 00, 02, 14, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1191 */ { 00, 02, 03, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 355
+1192 */ { 02, 01, 24, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1193 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1194 */ { 10, 01, 31, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1195 */ { 00, 02, 19, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1196 */ { 00, 02, 08, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1197 */ { 06, 01, 27, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1198 */ { 00, 02, 15, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1199 */ { 00, 02, 04, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1200 */ { 02, 01, 25, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1201 */ { 00, 02, 12, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1202 */ { 12, 02, 02, 0b0100100111011000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1203 */ { 00, 02, 21, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1204 */ { 00, 02, 10, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1205 */ { 08, 01, 29, 0b1010101001011000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1206 */ { 00, 02, 17, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1207 */ { 00, 02, 06, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1208 */ { 04, 01, 26, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
+1209 */ { 00, 02, 13, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1210 */ { 00, 02, 03, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1211 */ { 02, 01, 24, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1212 */ { 00, 02, 12, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1213 */ { 09, 01, 31, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1214 */ { 00, 02, 19, 0b0101010010110000 }, /* 29 30 29 30 29 30 29 29 30 29 30 30 354
+1215 */ { 00, 02, 08, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1216 */ { 07, 01, 28, 0b0110110100101000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
+1217 */ { 00, 02, 15, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1218 */ { 00, 02, 04, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1219 */ { 03, 01, 25, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1220 */ { 00, 02, 13, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1221 */ { 12, 02, 01, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1222 */ { 00, 02, 20, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1223 */ { 00, 02, 09, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1224 */ { 08, 01, 29, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1225 */ { 00, 02, 16, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1226 */ { 00, 02, 06, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1227 */ { 05, 01, 26, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1228 */ { 00, 02, 15, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1229 */ { 00, 02, 03, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1230 */ { 02, 01, 23, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1231 */ { 00, 02, 11, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1232 */ { 09, 01, 31, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1233 */ { 00, 02, 18, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1234 */ { 00, 02, 07, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1235 */ { 07, 01, 28, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1236 */ { 00, 02, 16, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1237 */ { 00, 02, 04, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1238 */ { 04, 01, 25, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1239 */ { 00, 02, 13, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1240 */ { 12, 02, 02, 0b1010100100111000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+1241 */ { 00, 02, 20, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1242 */ { 00, 02, 09, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1243 */ { 08, 01, 29, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1244 */ { 00, 02, 17, 0b1010111001010000 }, /* 30 29 30 29 30 30 30 29 29 30 29 30 355
+1245 */ { 00, 02, 06, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1246 */ { 04, 01, 26, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1247 */ { 00, 02, 14, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1248 */ { 00, 02, 04, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1249 */ { 02, 01, 23, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1250 */ { 00, 02, 10, 0b1110010100110000 }, /* 30 30 30 29 29 30 29 30 29 29 30 30 355
+1251 */ { 10, 01, 31, 0b0110110010011000 }, /* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
+1252 */ { 00, 02, 19, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1253 */ { 00, 02, 07, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1254 */ { 06, 01, 28, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1255 */ { 00, 02, 16, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1256 */ { 00, 02, 05, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1257 */ { 04, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1258 */ { 00, 02, 12, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1259 */ { 11, 02, 01, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1260 */ { 00, 02, 20, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1261 */ { 00, 02, 08, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+1262 */ { 09, 01, 29, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1263 */ { 00, 02, 17, 0b0101010101110000 }, /* 29 30 29 30 29 30 29 30 29 30 30 30 355
+1264 */ { 00, 02, 07, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
+1265 */ { 05, 01, 26, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1266 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1267 */ { 00, 02, 03, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1268 */ { 01, 01, 23, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1269 */ { 00, 02, 10, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1270 */ { 11, 01, 30, 0b1011010111000000 }, /* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
+1271 */ { 00, 02, 18, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1272 */ { 00, 02, 08, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1273 */ { 06, 01, 28, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1274 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1275 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1276 */ { 03, 01, 25, 0b0110101001011000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
+1277 */ { 00, 02, 12, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1278 */ { 11, 02, 01, 0b0110101100101000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1279 */ { 00, 02, 20, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1280 */ { 00, 02, 09, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1281 */ { 08, 01, 29, 0b0010101011101000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
+1282 */ { 00, 02, 17, 0b0100100111100000 }, /* 29 30 29 29 30 29 29 30 30 30 30 29 354
+1283 */ { 00, 02, 06, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1284 */ { 05, 01, 26, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1285 */ { 00, 02, 13, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+1286 */ { 00, 02, 02, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1287 */ { 02, 01, 22, 0b1111001010010000 }, /* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
+1288 */ { 00, 02, 10, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+1289 */ { 10, 01, 30, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1290 */ { 00, 02, 18, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1291 */ { 00, 02, 08, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1292 */ { 06, 01, 28, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1293 */ { 00, 02, 15, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1294 */ { 00, 02, 04, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1295 */ { 04, 01, 24, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1296 */ { 00, 02, 12, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1297 */ { 12, 01, 31, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+1298 */ { 00, 02, 19, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1299 */ { 00, 02, 09, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1300 */ { 08, 01, 30, 0b0000100101111000 }, /* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
+1301 */ { 00, 02, 18, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1302 */ { 00, 02, 07, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1303 */ { 05, 01, 27, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1304 */ { 00, 02, 14, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1305 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1306 */ { 01, 01, 23, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1307 */ { 00, 02, 11, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
+1308 */ { 11, 02, 01, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1309 */ { 00, 02, 19, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1310 */ { 00, 02, 08, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1311 */ { 07, 01, 28, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1312 */ { 00, 02, 16, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1313 */ { 00, 02, 04, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1314 */ { 03, 01, 25, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1315 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1316 */ { 00, 02, 02, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1317 */ { 01, 01, 22, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1318 */ { 00, 02, 10, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1319 */ { 08, 01, 30, 0b1010010101011000 }, /* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1320 */ { 00, 02, 18, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1321 */ { 00, 02, 06, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1322 */ { 05, 01, 26, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1323 */ { 00, 02, 14, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1324 */ { 00, 02, 04, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1325 */ { 01, 01, 23, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1326 */ { 00, 02, 11, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1327 */ { 09, 02, 01, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1328 */ { 00, 02, 20, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1329 */ { 00, 02, 08, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1330 */ { 07, 01, 28, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1331 */ { 00, 02, 16, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1332 */ { 00, 02, 05, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1333 */ { 03, 01, 25, 0b0100101110101000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
+1334 */ { 00, 02, 13, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1335 */ { 12, 02, 02, 0b1010011001110000 }, /* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
+1336 */ { 00, 02, 21, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
+1337 */ { 00, 02, 09, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+1338 */ { 08, 01, 29, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1339 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1340 */ { 00, 02, 06, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1341 */ { 05, 01, 26, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1342 */ { 00, 02, 14, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1343 */ { 00, 02, 04, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1344 */ { 02, 01, 24, 0b1010001011101000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1345 */ { 00, 02, 11, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+1346 */ { 10, 01, 31, 0b1101000101011000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1347 */ { 00, 02, 19, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1348 */ { 00, 02, 08, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1349 */ { 07, 01, 27, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1350 */ { 00, 02, 15, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1351 */ { 00, 02, 05, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1352 */ { 03, 01, 26, 0b0100100111011000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1353 */ { 00, 02, 13, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1354 */ { 00, 02, 02, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1355 */ { 01, 01, 22, 0b1101000101011000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1356 */ { 00, 02, 10, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1357 */ { 09, 01, 29, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1358 */ { 00, 02, 17, 0b0110101100100000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 354
+1359 */ { 00, 02, 06, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 355
+1360 */ { 05, 01, 27, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1361 */ { 00, 02, 14, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1362 */ { 00, 02, 04, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1363 */ { 03, 01, 24, 0b1010001010111000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
+1364 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1365 */ { 10, 01, 31, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
+1366 */ { 00, 02, 18, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1367 */ { 00, 02, 08, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1368 */ { 07, 01, 28, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1369 */ { 00, 02, 15, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
+1370 */ { 00, 02, 05, 0b0101001011100000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 354
+1371 */ { 03, 01, 25, 0b1100010101110000 }, /* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
+1372 */ { 00, 02, 13, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1373 */ { 11, 02, 01, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1374 */ { 00, 02, 20, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1375 */ { 00, 02, 09, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1376 */ { 09, 01, 30, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1377 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1378 */ { 00, 02, 06, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1379 */ { 05, 01, 27, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1380 */ { 00, 02, 15, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1381 */ { 00, 02, 03, 0b1010100011010000 }, /* 30 29 30 29 30 29 29 29 30 30 29 30 354
+1382 */ { 02, 01, 23, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1383 */ { 00, 02, 11, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1384 */ { 10, 01, 31, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1385 */ { 00, 02, 18, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1386 */ { 00, 02, 08, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1387 */ { 06, 01, 28, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1388 */ { 00, 02, 16, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1389 */ { 00, 02, 05, 0b0101000110110000 }, /* 29 30 29 30 29 29 29 30 30 29 30 30 354
+1390 */ { 04, 01, 25, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1391 */ { 00, 02, 13, 0b0110010100110000 }, /* 29 30 30 29 29 30 29 30 29 29 30 30 354
+1392 */ { 12, 02, 02, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1393 */ { 00, 02, 20, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1394 */ { 00, 02, 09, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1395 */ { 09, 01, 30, 0b0010101110101000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
+1396 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1397 */ { 00, 02, 06, 0b1100001101110000 }, /* 30 30 29 29 29 29 30 30 29 30 30 30 355
+1398 */ { 05, 01, 27, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1399 */ { 00, 02, 14, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1400 */ { 00, 02, 03, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
+1401 */ { 03, 01, 24, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1402 */ { 00, 02, 11, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1403 */ { 11, 02, 01, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1404 */ { 00, 02, 20, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1405 */ { 00, 02, 09, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1406 */ { 07, 01, 29, 0b1010001011101000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1407 */ { 00, 02, 17, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+1408 */ { 00, 02, 06, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
+1409 */ { 04, 01, 25, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1410 */ { 00, 02, 13, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1411 */ { 12, 02, 02, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
+1412 */ { 00, 02, 21, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1413 */ { 00, 02, 10, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1414 */ { 09, 01, 31, 0b0010010111011000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
+1415 */ { 00, 02, 19, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1416 */ { 00, 02, 08, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1417 */ { 05, 01, 27, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1418 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1419 */ { 00, 02, 04, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1420 */ { 01, 01, 24, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1421 */ { 00, 02, 11, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1422 */ { 12, 02, 01, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1423 */ { 00, 02, 20, 0b0100101101110000 }, /* 29 30 29 29 30 29 30 30 29 30 30 30 355
+1424 */ { 00, 02, 10, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1425 */ { 07, 01, 29, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1426 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1427 */ { 00, 02, 06, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1428 */ { 04, 01, 26, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1429 */ { 00, 02, 13, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1430 */ { 12, 02, 02, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
+1431 */ { 00, 02, 21, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
+1432 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1433 */ { 08, 01, 30, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1434 */ { 00, 02, 18, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1435 */ { 00, 02, 07, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1436 */ { 06, 01, 27, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1437 */ { 00, 02, 14, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1438 */ { 00, 02, 04, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1439 */ { 02, 01, 24, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1440 */ { 00, 02, 12, 0b1001010111100000 }, /* 30 29 29 30 29 30 29 30 30 30 30 29 355
+1441 */ { 11, 02, 01, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1442 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1443 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1444 */ { 07, 01, 29, 0b1101001001110000 }, /* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
+1445 */ { 00, 02, 16, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1446 */ { 00, 02, 05, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1447 */ { 04, 01, 26, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1448 */ { 00, 02, 14, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1449 */ { 00, 02, 02, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1450 */ { 01, 01, 23, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1451 */ { 00, 02, 11, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1452 */ { 09, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1453 */ { 00, 02, 18, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1454 */ { 00, 02, 07, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1455 */ { 06, 01, 27, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1456 */ { 00, 02, 15, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1457 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1458 */ { 02, 01, 24, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1459 */ { 00, 02, 12, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1460 */ { 11, 02, 02, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1461 */ { 00, 02, 19, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1462 */ { 00, 02, 08, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
+1463 */ { 07, 01, 29, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1464 */ { 00, 02, 16, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1465 */ { 00, 02, 05, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1466 */ { 03, 01, 26, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1467 */ { 00, 02, 14, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1468 */ { 00, 02, 03, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1469 */ { 02, 01, 22, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1470 */ { 00, 02, 10, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1471 */ { 09, 01, 30, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1472 */ { 00, 02, 18, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1473 */ { 00, 02, 06, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1474 */ { 06, 01, 27, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1475 */ { 00, 02, 15, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1476 */ { 00, 02, 05, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1477 */ { 02, 01, 24, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1478 */ { 00, 02, 12, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1479 */ { 10, 02, 01, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1480 */ { 00, 02, 20, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1481 */ { 00, 02, 08, 0b0111010010100000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 354
+1482 */ { 08, 01, 28, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1483 */ { 00, 02, 16, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1484 */ { 00, 02, 06, 0b0101001110110000 }, /* 29 30 29 30 29 29 30 30 30 29 30 30 355
+1485 */ { 04, 01, 26, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1486 */ { 00, 02, 14, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1487 */ { 00, 02, 03, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1488 */ { 01, 01, 23, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1489 */ { 00, 02, 10, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1490 */ { 09, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1491 */ { 00, 02, 18, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1492 */ { 00, 02, 07, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1493 */ { 05, 01, 27, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1494 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1495 */ { 00, 02, 04, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1496 */ { 03, 01, 25, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1497 */ { 00, 02, 11, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1498 */ { 11, 01, 31, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
+1499 */ { 00, 02, 19, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1500 */ { 00, 02, 09, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1501 */ { 07, 01, 29, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1502 */ { 00, 02, 17, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1503 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1504 */ { 04, 01, 27, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1505 */ { 00, 02, 14, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1506 */ { 00, 02, 03, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1507 */ { 01, 01, 23, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
+1508 */ { 00, 02, 11, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1509 */ { 09, 01, 31, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1510 */ { 00, 02, 19, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1511 */ { 00, 02, 08, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1512 */ { 05, 01, 29, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1513 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1514 */ { 00, 02, 05, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1515 */ { 04, 01, 25, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1516 */ { 00, 02, 13, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1517 */ { 12, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1518 */ { 00, 02, 20, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
+1519 */ { 00, 02, 10, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1520 */ { 08, 01, 30, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1521 */ { 00, 02, 17, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 355
+1522 */ { 00, 02, 07, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1523 */ { 04, 01, 27, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1524 */ { 00, 02, 14, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1525 */ { 12, 02, 02, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1526 */ { 00, 02, 21, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 355
+1527 */ { 00, 02, 11, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1528 */ { 10, 02, 01, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1529 */ { 00, 02, 19, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1530 */ { 00, 02, 08, 0b0101001011100000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 354
+1531 */ { 06, 01, 28, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1532 */ { 00, 02, 16, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1533 */ { 00, 02, 04, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1534 */ { 02, 01, 24, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1535 */ { 00, 02, 12, 0b1011010110010000 }, /* 30 29 30 30 29 30 29 30 30 29 29 30 355
+1536 */ { 12, 02, 02, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1537 */ { 00, 02, 20, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1538 */ { 00, 02, 10, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1539 */ { 07, 01, 30, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1540 */ { 00, 02, 18, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1541 */ { 00, 02, 06, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1542 */ { 05, 01, 26, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1543 */ { 00, 02, 14, 0b0110110010100000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 354
+1544 */ { 00, 02, 03, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1545 */ { 01, 01, 23, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1546 */ { 00, 02, 11, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+1547 */ { 09, 02, 01, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1548 */ { 00, 02, 20, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1549 */ { 00, 02, 08, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1550 */ { 06, 01, 28, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1551 */ { 00, 02, 15, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1552 */ { 00, 02, 05, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1553 */ { 03, 01, 24, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1554 */ { 00, 02, 12, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1555 */ { 11, 02, 02, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1556 */ { 00, 02, 21, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1557 */ { 00, 02, 09, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1558 */ { 07, 01, 30, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1559 */ { 00, 02, 17, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1560 */ { 00, 02, 06, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1561 */ { 05, 01, 26, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1562 */ { 00, 02, 14, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1563 */ { 00, 02, 03, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1564 */ { 02, 01, 24, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1565 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1566 */ { 10, 01, 31, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1567 */ { 00, 02, 19, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1568 */ { 00, 02, 08, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1569 */ { 06, 01, 27, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1570 */ { 00, 02, 15, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1571 */ { 00, 02, 05, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
+1572 */ { 02, 01, 25, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1573 */ { 00, 02, 12, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1574 */ { 12, 02, 02, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1575 */ { 00, 02, 21, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1576 */ { 00, 02, 10, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1577 */ { 08, 01, 29, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1578 */ { 00, 02, 17, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1579 */ { 00, 02, 06, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1580 */ { 04, 01, 26, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1581 */ { 00, 02, 14, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1582 */ { 00, 02, 03, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1583 */ { 02, 01, 24, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1584 */ { 00, 02, 12, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1585 */ { 09, 01, 31, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1586 */ { 00, 02, 18, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1587 */ { 00, 02, 07, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1588 */ { 06, 01, 28, 0b0110101101001000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1589 */ { 00, 02, 15, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1590 */ { 00, 02, 05, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1591 */ { 03, 01, 25, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1592 */ { 00, 02, 13, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1593 */ { 11, 02, 01, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1594 */ { 00, 02, 20, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1595 */ { 00, 02, 09, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1596 */ { 08, 01, 29, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1597 */ { 00, 02, 16, 0b1011010011010000 }, /* 30 29 30 30 29 30 29 29 30 30 29 30 355
+1598 */ { 00, 02, 06, 0b0101011010110000 }, /* 29 30 29 30 29 30 30 29 30 29 30 30 355
+1599 */ { 04, 01, 27, 0b0010011011011000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1600 */ { 00, 02, 15, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1601 */ { 00, 02, 03, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1602 */ { 02, 01, 23, 0b1100100110011000 }, /* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
+1603 */ { 00, 02, 11, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1604 */ { 09, 01, 31, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1605 */ { 00, 02, 18, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1606 */ { 00, 02, 07, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1607 */ { 06, 01, 28, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1608 */ { 00, 02, 16, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+1609 */ { 00, 02, 05, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+1610 */ { 03, 01, 25, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1611 */ { 00, 02, 13, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1612 */ { 11, 02, 02, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1613 */ { 00, 02, 19, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1614 */ { 00, 02, 09, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1615 */ { 08, 01, 29, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1616 */ { 00, 02, 17, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 355
+1617 */ { 00, 02, 06, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1618 */ { 04, 01, 26, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1619 */ { 00, 02, 14, 0b1010010011110000 }, /* 30 29 30 29 29 30 29 29 30 30 30 30 355
+1620 */ { 00, 02, 04, 0b0101001001100000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 353
+1621 */ { 02, 01, 22, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1622 */ { 00, 02, 10, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1623 */ { 10, 01, 31, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1624 */ { 00, 02, 19, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1625 */ { 00, 02, 07, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1626 */ { 06, 01, 28, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1627 */ { 00, 02, 16, 0b0100100111100000 }, /* 29 30 29 29 30 29 29 30 30 30 30 29 354
+1628 */ { 00, 02, 05, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1629 */ { 04, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1630 */ { 00, 02, 12, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1631 */ { 11, 02, 01, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1632 */ { 00, 02, 20, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1633 */ { 00, 02, 08, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+1634 */ { 08, 01, 29, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1635 */ { 00, 02, 17, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1636 */ { 00, 02, 07, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1637 */ { 04, 01, 26, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1638 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1639 */ { 00, 02, 03, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1640 */ { 01, 01, 23, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1641 */ { 00, 02, 10, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1642 */ { 11, 01, 30, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1643 */ { 00, 02, 19, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1644 */ { 00, 02, 08, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1645 */ { 06, 01, 28, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1646 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1647 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1648 */ { 03, 01, 25, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1649 */ { 00, 02, 11, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1650 */ { 11, 02, 01, 0b0110101101001000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1651 */ { 00, 02, 20, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1652 */ { 00, 02, 10, 0b0010101110100000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 354
+1653 */ { 07, 01, 29, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1654 */ { 00, 02, 17, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1655 */ { 00, 02, 06, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1656 */ { 05, 01, 26, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1657 */ { 00, 02, 13, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1658 */ { 00, 02, 02, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1659 */ { 03, 01, 23, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1660 */ { 00, 02, 11, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1661 */ { 07, 01, 30, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+1662 */ { 00, 02, 18, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 355
+1663 */ { 00, 02, 08, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1664 */ { 06, 01, 28, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1665 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1666 */ { 00, 02, 04, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1667 */ { 04, 01, 24, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1668 */ { 00, 02, 12, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1669 */ { 00, 02, 01, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
+1670 */ { 02, 01, 21, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1671 */ { 00, 02, 09, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1672 */ { 07, 01, 30, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1673 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1674 */ { 00, 02, 06, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1675 */ { 05, 01, 26, 0b0111010010101000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+1676 */ { 00, 02, 14, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1677 */ { 00, 02, 02, 0b1010110110010000 }, /* 30 29 30 29 30 30 29 30 30 29 29 30 355
+1678 */ { 03, 01, 23, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1679 */ { 00, 02, 11, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1680 */ { 08, 01, 31, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1681 */ { 00, 02, 18, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1682 */ { 00, 02, 07, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1683 */ { 06, 01, 27, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1684 */ { 00, 02, 15, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+1685 */ { 00, 02, 03, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1686 */ { 04, 01, 24, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1687 */ { 00, 02, 12, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1688 */ { 00, 02, 02, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1689 */ { 03, 01, 21, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1690 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1691 */ { 07, 01, 29, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1692 */ { 00, 02, 17, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+1693 */ { 00, 02, 05, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+1694 */ { 05, 01, 25, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1695 */ { 00, 02, 13, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+1696 */ { 00, 02, 03, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1697 */ { 03, 01, 23, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1698 */ { 00, 02, 11, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
+1699 */ { 07, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1700 */ { 00, 02, 19, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1701 */ { 00, 02, 08, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1702 */ { 06, 01, 28, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1703 */ { 00, 02, 16, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
+1704 */ { 00, 02, 05, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1705 */ { 04, 01, 25, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1706 */ { 00, 02, 13, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1707 */ { 00, 02, 03, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1708 */ { 03, 01, 23, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1709 */ { 00, 02, 10, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1710 */ { 07, 01, 30, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1711 */ { 00, 02, 17, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1712 */ { 00, 02, 07, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1713 */ { 05, 01, 26, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1714 */ { 00, 02, 14, 0b1010101011100000 }, /* 30 29 30 29 30 29 30 29 30 30 30 29 355
+1715 */ { 00, 02, 04, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1716 */ { 03, 01, 24, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1717 */ { 00, 02, 11, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1718 */ { 08, 01, 31, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1719 */ { 00, 02, 19, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1720 */ { 00, 02, 08, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1721 */ { 06, 01, 28, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1722 */ { 00, 02, 16, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1723 */ { 00, 02, 05, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1724 */ { 04, 01, 26, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1725 */ { 00, 02, 13, 0b0101001011010000 }, /* 29 30 29 30 29 29 30 29 30 30 29 30 354
+1726 */ { 00, 02, 02, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1727 */ { 03, 01, 22, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+1728 */ { 00, 02, 10, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1729 */ { 07, 01, 29, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1730 */ { 00, 02, 17, 0b1001110101010000 }, /* 30 29 29 30 30 30 29 30 29 30 29 30 355
+1731 */ { 00, 02, 07, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
+1732 */ { 05, 01, 27, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1733 */ { 00, 02, 14, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1734 */ { 00, 02, 04, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1735 */ { 04, 01, 24, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1736 */ { 00, 02, 12, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1737 */ { 09, 01, 31, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1738 */ { 00, 02, 19, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1739 */ { 00, 02, 08, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1740 */ { 06, 01, 29, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1741 */ { 00, 02, 16, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1742 */ { 00, 02, 05, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1743 */ { 04, 01, 26, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1744 */ { 00, 02, 13, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+1745 */ { 00, 02, 01, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 355
+1746 */ { 03, 01, 22, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1747 */ { 00, 02, 09, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1748 */ { 07, 01, 30, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1749 */ { 00, 02, 17, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1750 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1751 */ { 05, 01, 27, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1752 */ { 00, 02, 15, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+1753 */ { 00, 02, 03, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
+1754 */ { 04, 01, 23, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1755 */ { 00, 02, 11, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1756 */ { 09, 01, 31, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1757 */ { 00, 02, 18, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1758 */ { 00, 02, 08, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1759 */ { 06, 01, 29, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1760 */ { 00, 02, 17, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1761 */ { 00, 02, 05, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1762 */ { 05, 01, 25, 0b1011000101011000 }, /* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
+1763 */ { 00, 02, 13, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1764 */ { 00, 02, 02, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1765 */ { 02, 01, 21, 0b1011010110010000 }, /* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
+1766 */ { 00, 02, 09, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 355
+1767 */ { 07, 01, 30, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1768 */ { 00, 02, 18, 0b0101001101110000 }, /* 29 30 29 30 29 29 30 30 29 30 30 30 355
+1769 */ { 00, 02, 07, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1770 */ { 05, 01, 27, 0b0110001010111000 }, /* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
+1771 */ { 00, 02, 15, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1772 */ { 00, 02, 04, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1773 */ { 03, 01, 23, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1774 */ { 00, 02, 11, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1775 */ { 10, 01, 31, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1776 */ { 00, 02, 19, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1777 */ { 00, 02, 08, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1778 */ { 06, 01, 28, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1779 */ { 00, 02, 16, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1780 */ { 00, 02, 05, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1781 */ { 05, 01, 24, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1782 */ { 00, 02, 12, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1783 */ { 00, 02, 02, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1784 */ { 03, 01, 22, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1785 */ { 00, 02, 09, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1786 */ { 07, 01, 30, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1787 */ { 00, 02, 18, 0b0100101010110000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 354
+1788 */ { 00, 02, 07, 0b1010100011010000 }, /* 30 29 30 29 30 29 29 29 30 30 29 30 354
+1789 */ { 05, 01, 26, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1790 */ { 00, 02, 14, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1791 */ { 00, 02, 03, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1792 */ { 04, 01, 24, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1793 */ { 00, 02, 11, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1794 */ { 00, 01, 31, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1795 */ { 02, 01, 21, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1796 */ { 00, 02, 09, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1797 */ { 06, 01, 28, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1798 */ { 00, 02, 16, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1799 */ { 00, 02, 05, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1800 */ { 04, 01, 25, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1801 */ { 00, 02, 13, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1802 */ { 00, 02, 03, 0b0010101110100000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 354
+1803 */ { 02, 01, 23, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1804 */ { 00, 02, 11, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1805 */ { 06, 01, 31, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1806 */ { 00, 02, 18, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+1807 */ { 00, 02, 07, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
+1808 */ { 05, 01, 28, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1809 */ { 00, 02, 14, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
+1810 */ { 00, 02, 04, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
+1811 */ { 03, 01, 25, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1812 */ { 00, 02, 13, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1813 */ { 00, 02, 01, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
+1814 */ { 02, 01, 21, 0b1101000101101000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
+1815 */ { 00, 02, 09, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1816 */ { 06, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1817 */ { 00, 02, 16, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1818 */ { 00, 02, 05, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1819 */ { 04, 01, 26, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1820 */ { 00, 02, 14, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1821 */ { 00, 02, 03, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1822 */ { 03, 01, 23, 0b1010001011011000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+1823 */ { 00, 02, 11, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1824 */ { 07, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1825 */ { 00, 02, 18, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1826 */ { 00, 02, 07, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1827 */ { 05, 01, 27, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1828 */ { 00, 02, 15, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1829 */ { 00, 02, 04, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1830 */ { 04, 01, 25, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1831 */ { 00, 02, 13, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1832 */ { 09, 02, 02, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1833 */ { 00, 02, 20, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1834 */ { 00, 02, 09, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1835 */ { 06, 01, 29, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1836 */ { 00, 02, 17, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1837 */ { 00, 02, 05, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1838 */ { 04, 01, 26, 0b0101001101101000 }, /* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
+1839 */ { 00, 02, 14, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1840 */ { 00, 02, 03, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1841 */ { 03, 01, 23, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1842 */ { 00, 02, 10, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1843 */ { 07, 01, 30, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1844 */ { 00, 02, 18, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1845 */ { 00, 02, 07, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1846 */ { 05, 01, 27, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1847 */ { 00, 02, 15, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1848 */ { 00, 02, 05, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1849 */ { 04, 01, 24, 0b1010010101011000 }, /* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1850 */ { 00, 02, 12, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1851 */ { 08, 02, 01, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1852 */ { 00, 02, 20, 0b1011001010010000 }, /* 30 29 30 30 29 29 30 29 30 29 29 30 354
+1853 */ { 00, 02, 08, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1854 */ { 07, 01, 29, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1855 */ { 00, 02, 17, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1856 */ { 00, 02, 06, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1857 */ { 05, 01, 26, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1858 */ { 00, 02, 14, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1859 */ { 00, 02, 03, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1860 */ { 03, 01, 23, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1861 */ { 00, 02, 10, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1862 */ { 08, 01, 30, 0b1010110101001000 }, /* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
+1863 */ { 00, 02, 18, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1864 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1865 */ { 05, 01, 27, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1866 */ { 00, 02, 15, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1867 */ { 00, 02, 05, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1868 */ { 04, 01, 25, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1869 */ { 00, 02, 11, 0b1110010010100000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 354
+1870 */ { 10, 01, 31, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1871 */ { 00, 02, 19, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
+1872 */ { 00, 02, 09, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1873 */ { 06, 01, 29, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1874 */ { 00, 02, 17, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1875 */ { 00, 02, 06, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1876 */ { 05, 01, 26, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1877 */ { 00, 02, 13, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1878 */ { 00, 02, 02, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1879 */ { 03, 01, 22, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1880 */ { 00, 02, 10, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1881 */ { 07, 01, 30, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1882 */ { 00, 02, 18, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1883 */ { 00, 02, 08, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1884 */ { 05, 01, 28, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1885 */ { 00, 02, 15, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1886 */ { 00, 02, 04, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1887 */ { 04, 01, 24, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1888 */ { 00, 02, 12, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1889 */ { 00, 01, 31, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1890 */ { 02, 01, 21, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1891 */ { 00, 02, 09, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1892 */ { 06, 01, 30, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1893 */ { 00, 02, 17, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1894 */ { 00, 02, 06, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1895 */ { 05, 01, 26, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1896 */ { 00, 02, 13, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1897 */ { 00, 02, 02, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1898 */ { 03, 01, 22, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1899 */ { 00, 02, 10, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1900 */ { 08, 01, 31, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1901 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1902 */ { 00, 02, 08, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1903 */ { 05, 01, 29, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */ { 00, 02, 16, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1905 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1906 */ { 04, 01, 25, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1908 */ { 00, 02, 02, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1909 */ { 02, 01, 22, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */ { 00, 02, 10, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1911 */ { 06, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1913 */ { 00, 02, 06, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1914 */ { 05, 01, 26, 0b1101100101001000 }, /* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
+1915 */ { 00, 02, 14, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1916 */ { 00, 02, 04, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1917 */ { 02, 01, 23, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */ { 00, 02, 11, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1919 */ { 07, 02, 01, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1920 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1921 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1922 */ { 05, 01, 28, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */ { 00, 02, 16, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1924 */ { 00, 02, 05, 0b1010110101000000 }, /* 30 29 30 29 30 30 29 30 29 30 29 29 354
+1925 */ { 04, 01, 24, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1926 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1927 */ { 00, 02, 02, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1928 */ { 02, 01, 23, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1929 */ { 00, 02, 10, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1930 */ { 06, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */ { 00, 02, 17, 0b1110010010100000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 354
+1932 */ { 00, 02, 06, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1933 */ { 05, 01, 26, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */ { 00, 02, 14, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
+1935 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1936 */ { 03, 01, 24, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1937 */ { 00, 02, 11, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1938 */ { 07, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */ { 00, 02, 19, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1940 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1941 */ { 06, 01, 27, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */ { 00, 02, 15, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1943 */ { 00, 02, 05, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1944 */ { 04, 01, 26, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1945 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1946 */ { 00, 02, 02, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1947 */ { 02, 01, 22, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1949 */ { 07, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1950 */ { 00, 02, 17, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1951 */ { 00, 02, 06, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1952 */ { 05, 01, 27, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1953 */ { 00, 02, 14, 0b0100110110110000 }, /* 29 30 29 29 30 30 29 30 30 29 30 30 355
+1954 */ { 00, 02, 04, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+1955 */ { 03, 01, 24, 0b1001001010111000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1957 */ { 08, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1958 */ { 00, 02, 19, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1959 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1965 */ { 00, 02, 02, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1966 */ { 03, 01, 22, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1968 */ { 07, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1970 */ { 00, 02, 06, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1973 */ { 00, 02, 03, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1976 */ { 08, 01, 31, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1978 */ { 00, 02, 07, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1982 */ { 04, 01, 25, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1987 */ { 06, 01, 29, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1989 */ { 00, 02, 06, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1990 */ { 05, 01, 27, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1995 */ { 08, 01, 31, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */ { 00, 02, 19, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1997 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1998 */ { 05, 01, 28, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2001 */ { 04, 01, 24, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */ { 00, 02, 09, 0b0101011011000000 }, /* 29 30 29 30 29 30 30 29 30 30 29 29 354
+2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2012 */ { 03, 01, 23, 0b1011101001010000 }, /* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */ { 00, 02, 10, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
+2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2017 */ { 05, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2019 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2020 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2023 */ { 02, 01, 22, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */ { 00, 02, 17, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+2027 */ { 00, 02, 07, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+2028 */ { 05, 01, 27, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */ { 00, 02, 13, 0b1101100100110000 }, /* 30 30 29 30 30 29 29 30 29 29 30 30 355
+2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+2031 */ { 03, 01, 23, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+2036 */ { 06, 01, 28, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */ { 00, 02, 12, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+2041 */ { 00, 02, 01, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+2046 */ { 00, 02, 06, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */ { 00, 02, 14, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+2050 */ { 03, 01, 23, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+ */ };
internal override int MinCalendarYear
{
@@ -1249,7 +1248,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MIN_LUNISOLAR_YEAR,
@@ -1272,7 +1271,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
}
@@ -1306,8 +1305,6 @@ namespace System.Globalization
}
}
-
-
public override int[] Eras
{
get
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
index a98023dc9..7afe09474 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
@@ -52,23 +52,23 @@ namespace System.Globalization
internal int[] numberGroupSizes = new int[] { 3 };
internal int[] currencyGroupSizes = new int[] { 3 };
internal int[] percentGroupSizes = new int[] { 3 };
- internal String positiveSign = "+";
- internal String negativeSign = "-";
- internal String numberDecimalSeparator = ".";
- internal String numberGroupSeparator = ",";
- internal String currencyGroupSeparator = ",";
- internal String currencyDecimalSeparator = ".";
- internal String currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
- internal String nanSymbol = "NaN";
- internal String positiveInfinitySymbol = "Infinity";
- internal String negativeInfinitySymbol = "-Infinity";
- internal String percentDecimalSeparator = ".";
- internal String percentGroupSeparator = ",";
- internal String percentSymbol = "%";
- internal String perMilleSymbol = "\u2030";
-
-
- internal String[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+ internal string positiveSign = "+";
+ internal string negativeSign = "-";
+ internal string numberDecimalSeparator = ".";
+ internal string numberGroupSeparator = ",";
+ internal string currencyGroupSeparator = ",";
+ internal string currencyDecimalSeparator = ".";
+ internal string currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
+ internal string nanSymbol = "NaN";
+ internal string positiveInfinitySymbol = "Infinity";
+ internal string negativeInfinitySymbol = "-Infinity";
+ internal string percentDecimalSeparator = ".";
+ internal string percentGroupSeparator = ",";
+ internal string percentSymbol = "%";
+ internal string perMilleSymbol = "\u2030";
+
+
+ internal string[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
internal int numberDecimalDigits = 2;
internal int currencyDecimalDigits = 2;
@@ -90,7 +90,7 @@ namespace System.Globalization
{
}
- private static void VerifyDecimalSeparator(String decSep, String propertyName)
+ private static void VerifyDecimalSeparator(string decSep, string propertyName)
{
if (decSep == null)
{
@@ -104,7 +104,7 @@ namespace System.Globalization
}
}
- private static void VerifyGroupSeparator(String groupSep, String propertyName)
+ private static void VerifyGroupSeparator(string groupSep, string propertyName)
{
if (groupSep == null)
{
@@ -237,7 +237,7 @@ namespace System.Globalization
}
}
- public Object Clone()
+ public object Clone()
{
NumberFormatInfo n = (NumberFormatInfo)MemberwiseClone();
n.isReadOnly = false;
@@ -254,7 +254,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(CurrencyDecimalDigits),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -266,7 +266,7 @@ namespace System.Globalization
}
- public String CurrencyDecimalSeparator
+ public string CurrencyDecimalSeparator
{
get { return currencyDecimalSeparator; }
set
@@ -292,7 +292,7 @@ namespace System.Globalization
// Every element in the groupSize array should be between 1 and 9
// excpet the last element could be zero.
//
- internal static void CheckGroupSize(String propName, int[] groupSize)
+ internal static void CheckGroupSize(string propName, int[] groupSize)
{
for (int i = 0; i < groupSize.Length; i++)
{
@@ -325,7 +325,7 @@ namespace System.Globalization
}
VerifyWritable();
- Int32[] inputSizes = (Int32[])value.Clone();
+ int[] inputSizes = (int[])value.Clone();
CheckGroupSize(nameof(CurrencyGroupSizes), inputSizes);
currencyGroupSizes = inputSizes;
}
@@ -348,7 +348,7 @@ namespace System.Globalization
}
VerifyWritable();
- Int32[] inputSizes = (Int32[])value.Clone();
+ int[] inputSizes = (int[])value.Clone();
CheckGroupSize(nameof(NumberGroupSizes), inputSizes);
numberGroupSizes = inputSizes;
}
@@ -369,14 +369,14 @@ namespace System.Globalization
SR.ArgumentNull_Obj);
}
VerifyWritable();
- Int32[] inputSizes = (Int32[])value.Clone();
+ int[] inputSizes = (int[])value.Clone();
CheckGroupSize(nameof(PercentGroupSizes), inputSizes);
percentGroupSizes = inputSizes;
}
}
- public String CurrencyGroupSeparator
+ public string CurrencyGroupSeparator
{
get { return currencyGroupSeparator; }
set
@@ -388,7 +388,7 @@ namespace System.Globalization
}
- public String CurrencySymbol
+ public string CurrencySymbol
{
get { return currencySymbol; }
set
@@ -424,7 +424,7 @@ namespace System.Globalization
}
- public String NaNSymbol
+ public string NaNSymbol
{
get
{
@@ -453,7 +453,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(CurrencyNegativePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -477,7 +477,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(NumberNegativePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -501,7 +501,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(PercentPositivePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -525,7 +525,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(PercentNegativePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -537,7 +537,7 @@ namespace System.Globalization
}
- public String NegativeInfinitySymbol
+ public string NegativeInfinitySymbol
{
get
{
@@ -556,7 +556,7 @@ namespace System.Globalization
}
- public String NegativeSign
+ public string NegativeSign
{
get { return negativeSign; }
set
@@ -581,7 +581,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(NumberDecimalDigits),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -593,7 +593,7 @@ namespace System.Globalization
}
- public String NumberDecimalSeparator
+ public string NumberDecimalSeparator
{
get { return numberDecimalSeparator; }
set
@@ -605,7 +605,7 @@ namespace System.Globalization
}
- public String NumberGroupSeparator
+ public string NumberGroupSeparator
{
get { return numberGroupSeparator; }
set
@@ -626,7 +626,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(CurrencyPositivePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -638,7 +638,7 @@ namespace System.Globalization
}
- public String PositiveInfinitySymbol
+ public string PositiveInfinitySymbol
{
get
{
@@ -657,7 +657,7 @@ namespace System.Globalization
}
- public String PositiveSign
+ public string PositiveSign
{
get { return positiveSign; }
set
@@ -682,7 +682,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(PercentDecimalDigits),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -694,7 +694,7 @@ namespace System.Globalization
}
- public String PercentDecimalSeparator
+ public string PercentDecimalSeparator
{
get { return percentDecimalSeparator; }
set
@@ -706,7 +706,7 @@ namespace System.Globalization
}
- public String PercentGroupSeparator
+ public string PercentGroupSeparator
{
get { return percentGroupSeparator; }
set
@@ -718,7 +718,7 @@ namespace System.Globalization
}
- public String PercentSymbol
+ public string PercentSymbol
{
get
{
@@ -737,7 +737,7 @@ namespace System.Globalization
}
- public String PerMilleSymbol
+ public string PerMilleSymbol
{
get { return perMilleSymbol; }
set
@@ -754,7 +754,7 @@ namespace System.Globalization
public string[] NativeDigits
{
- get { return (String[])nativeDigits.Clone(); }
+ get { return (string[])nativeDigits.Clone(); }
set
{
VerifyWritable();
@@ -774,7 +774,7 @@ namespace System.Globalization
}
}
- public Object GetFormat(Type formatType)
+ public object GetFormat(Type formatType)
{
return formatType == typeof(NumberFormatInfo) ? this : null;
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
index 10912f85b..a6f964d34 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
@@ -117,7 +117,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
minDate,
@@ -140,7 +140,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -157,7 +157,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -282,7 +282,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -462,7 +462,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -521,7 +521,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -560,7 +560,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(value),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -589,7 +589,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
index 2cad7bb31..8416257d9 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
@@ -31,7 +31,7 @@ namespace System.Globalization
//
// Name of this region (ie: es-US): serialized, the field used for deserialization
//
- internal String _name;
+ internal string _name;
//
// The CultureData instance that we are going to read data from.
@@ -54,7 +54,7 @@ namespace System.Globalization
// In Silverlight we enforce that RegionInfos must be created with a full culture name
//
////////////////////////////////////////////////////////////////////////
- public RegionInfo(String name)
+ public RegionInfo(string name)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
@@ -71,7 +71,7 @@ namespace System.Globalization
_cultureData = CultureData.GetCultureDataForRegion(name, true);
if (_cultureData == null)
throw new ArgumentException(
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.Argument_InvalidCultureName, name), nameof(name));
@@ -157,7 +157,7 @@ namespace System.Globalization
// Returns the name of the region (ie: en-US)
//
////////////////////////////////////////////////////////////////////////
- public virtual String Name
+ public virtual string Name
{
get
{
@@ -173,7 +173,7 @@ namespace System.Globalization
// Returns the name of the region in English. (ie: United States)
//
////////////////////////////////////////////////////////////////////////
- public virtual String EnglishName
+ public virtual string EnglishName
{
get
{
@@ -190,7 +190,7 @@ namespace System.Globalization
// if the current UI language is en-US)
//
////////////////////////////////////////////////////////////////////////
- public virtual String DisplayName
+ public virtual string DisplayName
{
get
{
@@ -207,7 +207,7 @@ namespace System.Globalization
// WARNING: You need a full locale name for this to make sense.
//
////////////////////////////////////////////////////////////////////////
- public virtual String NativeName
+ public virtual string NativeName
{
get
{
@@ -222,7 +222,7 @@ namespace System.Globalization
// Returns the two letter ISO region name (ie: US)
//
////////////////////////////////////////////////////////////////////////
- public virtual String TwoLetterISORegionName
+ public virtual string TwoLetterISORegionName
{
get
{
@@ -237,7 +237,7 @@ namespace System.Globalization
// Returns the three letter ISO region name (ie: USA)
//
////////////////////////////////////////////////////////////////////////
- public virtual String ThreeLetterISORegionName
+ public virtual string ThreeLetterISORegionName
{
get
{
@@ -252,7 +252,7 @@ namespace System.Globalization
// Returns the three letter windows region name (ie: USA)
//
////////////////////////////////////////////////////////////////////////
- public virtual String ThreeLetterWindowsRegionName
+ public virtual string ThreeLetterWindowsRegionName
{
get
{
@@ -324,7 +324,7 @@ namespace System.Globalization
// Currency Symbol for this locale, ie: Fr. or $
//
////////////////////////////////////////////////////////////////////////
- public virtual String CurrencySymbol
+ public virtual string CurrencySymbol
{
get
{
@@ -339,7 +339,7 @@ namespace System.Globalization
// ISO Currency Symbol for this locale, ie: CHF
//
////////////////////////////////////////////////////////////////////////
- public virtual String ISOCurrencySymbol
+ public virtual string ISOCurrencySymbol
{
get
{
@@ -358,7 +358,7 @@ namespace System.Globalization
// (ie: en-US)
//
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
RegionInfo that = value as RegionInfo;
if (that != null)
@@ -391,7 +391,7 @@ namespace System.Globalization
// Implements Object.ToString(). Returns the name of the Region, ie: es-US
//
////////////////////////////////////////////////////////////////////////
- public override String ToString()
+ public override string ToString()
{
return (Name);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs b/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
index 647db75b6..962494625 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
@@ -33,7 +33,7 @@ namespace System.Globalization
// The following constructor is designed to be called from CompareInfo to get the
// the sort key of specific string for synthetic culture
//
- internal SortKey(String localeName, String str, CompareOptions options, byte[] keyData)
+ internal SortKey(string localeName, string str, CompareOptions options, byte[] keyData)
{
_keyData = keyData;
_localeName = localeName;
@@ -49,7 +49,7 @@ namespace System.Globalization
// of SortKey.
//
////////////////////////////////////////////////////////////////////////
- public virtual String OriginalString
+ public virtual string OriginalString
{
get
{
@@ -133,7 +133,7 @@ namespace System.Globalization
// or not object refers to the same SortKey as the current instance.
//
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
SortKey that = value as SortKey;
@@ -167,7 +167,7 @@ namespace System.Globalization
// SortKey.
//
////////////////////////////////////////////////////////////////////////
- public override String ToString()
+ public override string ToString()
{
return ("SortKey - " + _localeName + ", " + _options + ", " + _string);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
index aa62b2c47..f7be252bf 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
@@ -32,7 +32,7 @@ namespace System.Globalization
this.String = value;
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
StringInfo that = value as StringInfo;
if (that != null)
@@ -266,7 +266,7 @@ namespace System.Globalization
{
if (index == len)
{
- return (String.Empty);
+ return (string.Empty);
}
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
index c5161138d..e2455cd5e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
@@ -243,7 +243,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -268,7 +268,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
index 60e84f7f3..451fc3074 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
@@ -263,7 +263,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MIN_LUNISOLAR_YEAR,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
index 8b0f102a7..7d8ff64a3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
@@ -21,7 +21,7 @@ namespace System.Globalization
public class TextElementEnumerator : IEnumerator
{
- private String _str;
+ private string _str;
private int _index;
private int _startIndex;
@@ -33,7 +33,7 @@ namespace System.Globalization
private int _charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not.
- internal TextElementEnumerator(String str, int startIndex, int strLen)
+ internal TextElementEnumerator(string str, int startIndex, int strLen)
{
Debug.Assert(str != null, "TextElementEnumerator(): str != null");
Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
@@ -61,7 +61,7 @@ namespace System.Globalization
// Get the current text element.
//
- public Object Current
+ public object Current
{
get
{
@@ -73,7 +73,7 @@ namespace System.Globalization
// Get the current text element.
//
- public String GetTextElement()
+ public string GetTextElement()
{
if (_index == _startIndex)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
index d13d3e8ce..c431e462b 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
@@ -13,116 +13,7 @@ namespace System.Globalization
{
private Tristate _needsTurkishCasing = Tristate.NotInitialized;
- private void FinishInitialization()
- {
- }
-
- private unsafe string ChangeCase(string s, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
-
- Debug.Assert(s != null);
-
- if (s.Length == 0)
- {
- return string.Empty;
- }
-
- string result = string.FastAllocateString(s.Length);
-
- fixed (char* pSource = s)
- {
- fixed (char* pResult = result)
- {
-#if CORECLR
- if (IsAsciiCasingSameAsInvariant && s.IsAscii())
- {
- int length = s.Length;
- char* a = pSource, b = pResult;
- if (toUpper)
- {
- while (length-- != 0)
- {
- *b++ = ToUpperAsciiInvariant(*a++);
- }
- }
- else
- {
- while (length-- != 0)
- {
- *b++ = ToLowerAsciiInvariant(*a++);
- }
- }
- }
- else
-#endif
- {
- ChangeCase(pSource, s.Length, pResult, result.Length, toUpper);
- }
- }
- }
-
- return result;
- }
-
- internal unsafe void ChangeCase(ReadOnlySpan<char> source, Span<char> destination, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
- Debug.Assert(destination.Length >= source.Length);
-
- if (source.IsEmpty)
- {
- return;
- }
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- {
- fixed (char* pResult = &MemoryMarshal.GetReference(destination))
- {
- if (IsAsciiCasingSameAsInvariant)
- {
- int length = 0;
- char* a = pSource, b = pResult;
- if (toUpper)
- {
- while (length < source.Length && *a < 0x80)
- {
- *b++ = ToUpperAsciiInvariant(*a++);
- length++;
- }
- }
- else
- {
- while (length < source.Length && *a < 0x80)
- {
- *b++ = ToLowerAsciiInvariant(*a++);
- length++;
- }
- }
-
- if (length != source.Length)
- {
- ChangeCase(a, source.Length - length, b, destination.Length - length, toUpper);
- }
- }
- else
- {
- ChangeCase(pSource, source.Length, pResult, destination.Length, toUpper);
- }
- }
- }
- }
-
- private unsafe char ChangeCase(char c, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
-
- char dst = default(char);
-
- ChangeCase(&c, 1, &dst, 1, toUpper);
-
- return dst;
- }
+ private void FinishInitialization() { }
// -----------------------------
// ---- PAL layer ends here ----
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
index 015b37fcc..6e5e32100 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Runtime.InteropServices;
namespace System.Globalization
{
@@ -24,115 +23,33 @@ namespace System.Globalization
_sortHandle = ret > 0 ? handle : IntPtr.Zero;
}
- private unsafe string ChangeCase(string s, bool toUpper)
+ private unsafe void ChangeCase(char* pSource, int pSourceLen, char* pResult, int pResultLen, bool toUpper)
{
Debug.Assert(!_invariantMode);
-
- Debug.Assert(s != null);
-
- //
- // Get the length of the string.
- //
- int nLengthInput = s.Length;
-
- //
- // Check if we have the empty string.
- //
- if (nLengthInput == 0)
- {
- return s;
- }
-
- int ret;
+ Debug.Assert(pSource != null);
+ Debug.Assert(pResult != null);
+ Debug.Assert(pSourceLen >= 0);
+ Debug.Assert(pResultLen >= 0);
+ Debug.Assert(pSourceLen <= pResultLen);
// Check for Invariant to avoid A/V in LCMapStringEx
uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
- //
- // Create the result string.
- //
- string result = string.FastAllocateString(nLengthInput);
-
- fixed (char* pSource = s)
- fixed (char* pResult = result)
- {
- ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
- pSource,
- nLengthInput,
- pResult,
- nLengthInput,
- null,
- null,
- _sortHandle);
- }
-
+ int ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
+ linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
+ pSource,
+ pSourceLen,
+ pResult,
+ pSourceLen,
+ null,
+ null,
+ _sortHandle);
if (ret == 0)
{
throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
}
- Debug.Assert(ret == nLengthInput, "Expected getting the same length of the original string");
- return result;
- }
-
- internal unsafe void ChangeCase(ReadOnlySpan<char> source, Span<char> destination, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
- Debug.Assert(destination.Length >= source.Length);
-
- if (source.IsEmpty)
- {
- return;
- }
-
- int ret;
-
- // Check for Invariant to avoid A/V in LCMapStringEx
- uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pResult = &MemoryMarshal.GetReference(destination))
- {
- ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
- pSource,
- source.Length,
- pResult,
- source.Length,
- null,
- null,
- _sortHandle);
- }
-
- if (ret == 0)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
-
- Debug.Assert(ret == source.Length, "Expected getting the same length of the original span");
- }
-
- private unsafe char ChangeCase(char c, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
-
- char retVal = '\0';
-
- // Check for Invariant to avoid A/V in LCMapStringEx
- uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
-
- Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
- &c,
- 1,
- &retVal,
- 1,
- null,
- null,
- _sortHandle);
-
- return retVal;
+ Debug.Assert(ret == pSourceLen, "Expected getting the same length of the original string");
}
// PAL Ends here
@@ -143,9 +60,6 @@ namespace System.Globalization
private const uint LCMAP_LOWERCASE = 0x00000100;
private const uint LCMAP_UPPERCASE = 0x00000200;
- private static bool IsInvariantLocale(string localeName)
- {
- return localeName == "";
- }
+ private static bool IsInvariantLocale(string localeName) => localeName == "";
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
index 631c8c0f1..8073b4b56 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
@@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////////////
using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
@@ -75,22 +76,11 @@ namespace System.Globalization
FinishInitialization();
}
- void IDeserializationCallback.OnDeserialization(Object sender)
+ void IDeserializationCallback.OnDeserialization(object sender)
{
throw new PlatformNotSupportedException();
}
- //
- // Internal ordinal comparison functions
- //
-
- internal static int GetHashCodeOrdinalIgnoreCase(string s)
- {
- // This is the same as an case insensitive hash for Invariant
- // (not necessarily true for sorting, but OK for casing & then we apply normal hash code rules)
- return Invariant.GetCaseInsensitiveHashCode(s);
- }
-
public virtual int ANSICodePage => _cultureData.IDEFAULTANSICODEPAGE;
public virtual int OEMCodePage => _cultureData.IDEFAULTOEMCODEPAGE;
@@ -212,7 +202,224 @@ namespace System.Globalization
return ChangeCase(str, toUpper: false);
}
- private unsafe string ToLowerAsciiInvariant(string s)
+ private unsafe char ChangeCase(char c, bool toUpper)
+ {
+ Debug.Assert(!_invariantMode);
+
+ char dst = default;
+ ChangeCase(&c, 1, &dst, 1, toUpper);
+ return dst;
+ }
+
+ private unsafe string ChangeCase(string source, bool toUpper)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(source != null);
+
+ // If the string is empty, we're done.
+ if (source.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ int sourcePos = 0;
+ string result = null;
+
+ // If this culture's casing for ASCII is the same as invariant, try to take
+ // a fast path that'll work in managed code and ASCII rather than calling out
+ // to the OS for culture-aware casing.
+ if (IsAsciiCasingSameAsInvariant)
+ {
+ if (toUpper)
+ {
+ // Loop through each character.
+ for (sourcePos = 0; sourcePos < source.Length; sourcePos++)
+ {
+ // If the character is lower-case, we're going to need to allocate a string.
+ char c = source[sourcePos];
+ if ((uint)(c - 'a') <= 'z' - 'a')
+ {
+ // Allocate the result string.
+ result = string.FastAllocateString(source.Length);
+ fixed (char* pResult = result)
+ {
+ // Store all of characters examined thus far.
+ if (sourcePos > 0)
+ {
+ source.AsSpan(0, sourcePos).CopyTo(new Span<char>(pResult, sourcePos));
+ }
+
+ // And store the current character, upper-cased.
+ char* d = pResult + sourcePos;
+ *d++ = (char)(c & ~0x20);
+ sourcePos++;
+
+ // Then continue looping through the remainder of the characters. If we hit
+ // a non-ASCII character, bail to fall back to culture-aware casing.
+ for (; sourcePos < source.Length; sourcePos++)
+ {
+ c = source[sourcePos];
+ if ((uint)(c - 'a') <= 'z' - 'a')
+ {
+ *d++ = (char)(c & ~0x20);
+ }
+ else if (!IsAscii(c))
+ {
+ break;
+ }
+ else
+ {
+ *d++ = c;
+ }
+ }
+ }
+
+ break;
+ }
+ else if (!IsAscii(c))
+ {
+ // The character isn't ASCII; bail to fall back to a culture-aware casing.
+ break;
+ }
+ }
+ }
+ else // toUpper == false
+ {
+ // Loop through each character.
+ for (sourcePos = 0; sourcePos < source.Length; sourcePos++)
+ {
+ // If the character is upper-case, we're going to need to allocate a string.
+ char c = source[sourcePos];
+ if ((uint)(c - 'A') <= 'Z' - 'A')
+ {
+ // Allocate the result string.
+ result = string.FastAllocateString(source.Length);
+ fixed (char* pResult = result)
+ {
+ // Store all of characters examined thus far.
+ if (sourcePos > 0)
+ {
+ source.AsSpan(0, sourcePos).CopyTo(new Span<char>(pResult, sourcePos));
+ }
+
+ // And store the current character, lower-cased.
+ char* d = pResult + sourcePos;
+ *d++ = (char)(c | 0x20);
+ sourcePos++;
+
+ // Then continue looping through the remainder of the characters. If we hit
+ // a non-ASCII character, bail to fall back to culture-aware casing.
+ for (; sourcePos < source.Length; sourcePos++)
+ {
+ c = source[sourcePos];
+ if ((uint)(c - 'A') <= 'Z' - 'A')
+ {
+ *d++ = (char)(c | 0x20);
+ }
+ else if (!IsAscii(c))
+ {
+ break;
+ }
+ else
+ {
+ *d++ = c;
+ }
+ }
+ }
+
+ break;
+ }
+ else if (!IsAscii(c))
+ {
+ // The character isn't ASCII; bail to fall back to a culture-aware casing.
+ break;
+ }
+ }
+ }
+
+ // If we successfully iterated through all of the characters, we didn't need to fall back
+ // to culture-aware casing. In that case, if we allocated a result string, use it, otherwise
+ // just return the original string, as no modifications were necessary.
+ if (sourcePos == source.Length)
+ {
+ return result ?? source;
+ }
+ }
+
+ // Falling back to culture-aware casing. Make sure we have a result string to write into.
+ // If we need to allocate the result string, we'll also need to copy over to it any
+ // characters already examined.
+ if (result == null)
+ {
+ result = string.FastAllocateString(source.Length);
+ if (sourcePos > 0)
+ {
+ fixed (char* pResult = result)
+ {
+ source.AsSpan(0, sourcePos).CopyTo(new Span<char>(pResult, sourcePos));
+ }
+ }
+ }
+
+ // Do the casing operation on everything after what we already processed.
+ fixed (char* pSource = source)
+ {
+ fixed (char* pResult = result)
+ {
+ ChangeCase(pSource + sourcePos, source.Length - sourcePos, pResult + sourcePos, result.Length - sourcePos, toUpper);
+ }
+ }
+
+ return result;
+ }
+
+ internal unsafe void ChangeCase(ReadOnlySpan<char> source, Span<char> destination, bool toUpper)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(destination.Length >= source.Length);
+
+ if (source.IsEmpty)
+ {
+ return;
+ }
+
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pResult = &MemoryMarshal.GetReference(destination))
+ {
+ if (IsAsciiCasingSameAsInvariant)
+ {
+ int length = 0;
+ char* a = pSource, b = pResult;
+ if (toUpper)
+ {
+ while (length < source.Length && *a < 0x80)
+ {
+ *b++ = ToUpperAsciiInvariant(*a++);
+ length++;
+ }
+ }
+ else
+ {
+ while (length < source.Length && *a < 0x80)
+ {
+ *b++ = ToLowerAsciiInvariant(*a++);
+ length++;
+ }
+ }
+
+ if (length != source.Length)
+ {
+ ChangeCase(a, source.Length - length, b, destination.Length - length, toUpper);
+ }
+ }
+ else
+ {
+ ChangeCase(pSource, source.Length, pResult, destination.Length, toUpper);
+ }
+ }
+ }
+
+ private static unsafe string ToLowerAsciiInvariant(string s)
{
if (s.Length == 0)
{
@@ -258,7 +465,7 @@ namespace System.Globalization
}
}
- internal void ToLowerAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
+ internal static void ToLowerAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
{
Debug.Assert(destination.Length >= source.Length);
@@ -268,7 +475,7 @@ namespace System.Globalization
}
}
- private unsafe string ToUpperAsciiInvariant(string s)
+ private static unsafe string ToUpperAsciiInvariant(string s)
{
if (s.Length == 0)
{
@@ -314,7 +521,7 @@ namespace System.Globalization
}
}
- internal void ToUpperAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
+ internal static void ToUpperAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
{
Debug.Assert(destination.Length >= source.Length);
@@ -405,7 +612,7 @@ namespace System.Globalization
// or not object refers to the same CultureInfo as the current instance.
//
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
TextInfo that = obj as TextInfo;
@@ -602,11 +809,20 @@ namespace System.Globalization
{
Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!");
- // for surrogate pairs do a simple ToUpper operation on the substring
if (charLen == 2)
{
- // Surrogate pair
- result.Append(ToUpper(input.Substring(inputIndex, charLen)));
+ // for surrogate pairs do a ToUpper operation on the substring
+ ReadOnlySpan<char> src = input.AsSpan(inputIndex, 2);
+ if (_invariantMode)
+ {
+ result.Append(src); // surrogate pair in invariant mode, so changing case is a nop
+ }
+ else
+ {
+ Span<char> dst = stackalloc char[2];
+ ChangeCase(src, dst, toUpper: true);
+ result.Append(dst);
+ }
inputIndex++;
}
else
@@ -693,64 +909,5 @@ namespace System.Globalization
|| uc == UnicodeCategory.ModifierLetter
|| uc == UnicodeCategory.OtherLetter);
}
-
- //
- // Get case-insensitive hash code for the specified string.
- //
- internal unsafe int GetCaseInsensitiveHashCode(string str)
- {
- // Validate inputs
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- // This code assumes that ASCII casing is safe for whatever context is passed in.
- // this is true today, because we only ever call these methods on Invariant. It would be ideal to refactor
- // these methods so they were correct by construction and we could only ever use Invariant.
-
- uint hash = 5381;
- uint c;
-
- // Note: We assume that str contains only ASCII characters until
- // we hit a non-ASCII character to optimize the common case.
- for (int i = 0; i < str.Length; i++)
- {
- c = str[i];
- if (c >= 0x80)
- {
- return GetCaseInsensitiveHashCodeSlow(str);
- }
-
- // If we have a lowercase character, ANDing off 0x20
- // will make it an uppercase character.
- if ((c - 'a') <= ('z' - 'a'))
- {
- c = (uint)((int)c & ~0x20);
- }
-
- hash = ((hash << 5) + hash) ^ c;
- }
-
- return (int)hash;
- }
-
- private unsafe int GetCaseInsensitiveHashCodeSlow(string str)
- {
- Debug.Assert(str != null);
-
- string upper = ToUpper(str);
-
- uint hash = 5381;
- uint c;
-
- for (int i = 0; i < upper.Length; i++)
- {
- c = upper[i];
- hash = ((hash << 5) + hash) ^ c;
- }
-
- return (int)hash;
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
index 4f8fd8f01..1175185dd 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
@@ -206,7 +206,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
index a66e4600a..5e553d56b 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
@@ -2,9 +2,11 @@
// 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.Text;
+using System.Buffers.Text;
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Text;
namespace System.Globalization
{
@@ -35,159 +37,300 @@ namespace System.Globalization
internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: false);
internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: true);
- internal enum Pattern
- {
- None = 0,
- Minimum = 1,
- Full = 2,
- }
/// <summary>Main method called from TimeSpan.ToString.</summary>
- internal static string Format(TimeSpan value, string format, IFormatProvider formatProvider) =>
- StringBuilderCache.GetStringAndRelease(FormatToBuilder(value, format, formatProvider));
-
- /// <summary>Main method called from TimeSpan.TryFormat.</summary>
- internal static bool TryFormat(TimeSpan value, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider formatProvider)
+ internal static string Format(TimeSpan value, string format, IFormatProvider formatProvider)
{
- StringBuilder sb = FormatToBuilder(value, format, formatProvider);
- if (sb.Length <= destination.Length)
+ if (string.IsNullOrEmpty(format))
{
- charsWritten = sb.Length;
- sb.CopyTo(0, destination, sb.Length);
- StringBuilderCache.Release(sb);
- return true;
+ return FormatC(value); // formatProvider ignored, as "c" is invariant
}
- else
+
+ if (format.Length == 1)
{
- StringBuilderCache.Release(sb);
- charsWritten = 0;
- return false;
+ char c = format[0];
+
+ if (c == 'c' || (c | 0x20) == 't') // special-case to optimize the default TimeSpan format
+ {
+ return FormatC(value); // formatProvider ignored, as "c" is invariant
+ }
+
+ if ((c | 0x20) == 'g') // special-case to optimize the remaining 'g'/'G' standard formats
+ {
+ return FormatG(value, DateTimeFormatInfo.GetInstance(formatProvider), c == 'G' ? StandardFormat.G : StandardFormat.g);
+ }
+
+ throw new FormatException(SR.Format_InvalidString);
}
+
+ return StringBuilderCache.GetStringAndRelease(FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null));
}
- private static StringBuilder FormatToBuilder(TimeSpan value, ReadOnlySpan<char> format, IFormatProvider formatProvider)
+ /// <summary>Main method called from TimeSpan.TryFormat.</summary>
+ internal static bool TryFormat(TimeSpan value, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider formatProvider)
{
if (format.Length == 0)
{
- format = "c";
+ return TryFormatStandard(value, StandardFormat.C, null, destination, out charsWritten);
}
- // Standard formats
if (format.Length == 1)
{
- char f = format[0];
- switch (f)
+ char c = format[0];
+ if (c == 'c' || ((c | 0x20) == 't'))
{
- case 'c':
- case 't':
- case 'T':
- return FormatStandard(
- value,
- isInvariant: true,
- format: format,
- pattern: Pattern.Minimum);
-
- case 'g':
- case 'G':
- DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(formatProvider);
- return FormatStandard(
- value,
- isInvariant: false,
- format: value.Ticks < 0 ? dtfi.FullTimeSpanNegativePattern : dtfi.FullTimeSpanPositivePattern,
- pattern: f == 'g' ? Pattern.Minimum : Pattern.Full);
-
- default:
+ return TryFormatStandard(value, StandardFormat.C, null, destination, out charsWritten);
+ }
+ else
+ {
+ StandardFormat sf =
+ c == 'g' ? StandardFormat.g :
+ c == 'G' ? StandardFormat.G :
throw new FormatException(SR.Format_InvalidString);
+ return TryFormatStandard(value, sf, DateTimeFormatInfo.GetInstance(formatProvider).DecimalSeparator, destination, out charsWritten);
}
}
- // Custom formats
- return FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null);
+ StringBuilder sb = FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null);
+
+ if (sb.Length <= destination.Length)
+ {
+ sb.CopyTo(0, destination, sb.Length);
+ charsWritten = sb.Length;
+ StringBuilderCache.Release(sb);
+ return true;
+ }
+
+ charsWritten = 0;
+ StringBuilderCache.Release(sb);
+ return false;
}
- /// <summary>Format the TimeSpan instance using the specified format.</summary>
- private static StringBuilder FormatStandard(TimeSpan value, bool isInvariant, ReadOnlySpan<char> format, Pattern pattern)
+ internal static string FormatC(TimeSpan value)
{
- StringBuilder sb = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
- int day = (int)(value.Ticks / TimeSpan.TicksPerDay);
- long time = value.Ticks % TimeSpan.TicksPerDay;
+ Span<char> destination = stackalloc char[26]; // large enough for any "c" TimeSpan
+ TryFormatStandard(value, StandardFormat.C, null, destination, out int charsWritten);
+ return new string(destination.Slice(0, charsWritten));
+ }
- if (value.Ticks < 0)
+ private static string FormatG(TimeSpan value, DateTimeFormatInfo dtfi, StandardFormat format)
+ {
+ string decimalSeparator = dtfi.DecimalSeparator;
+ int maxLength = 25 + decimalSeparator.Length; // large enough for any "g"/"G" TimeSpan
+ Span<char> destination = maxLength < 128 ?
+ stackalloc char[maxLength] :
+ new char[maxLength]; // the chances of needing this case are almost 0, as DecimalSeparator.Length will basically always == 1
+ TryFormatStandard(value, format, decimalSeparator, destination, out int charsWritten);
+ return new string(destination.Slice(0, charsWritten));
+ }
+
+ private enum StandardFormat { C, G, g }
+
+ private static bool TryFormatStandard(TimeSpan value, StandardFormat format, string decimalSeparator, Span<char> destination, out int charsWritten)
+ {
+ Debug.Assert(format == StandardFormat.C || format == StandardFormat.G || format == StandardFormat.g);
+
+ // First, calculate how large an output buffer is needed to hold the entire output.
+ int requiredOutputLength = 8; // start with "hh:mm:ss" and adjust as necessary
+
+ uint fraction;
+ ulong totalSecondsRemaining;
{
- day = -day;
- time = -time;
+ // Turn this into a non-negative TimeSpan if possible.
+ long ticks = value.Ticks;
+ if (ticks < 0)
+ {
+ requiredOutputLength = 9; // requiredOutputLength + 1 for the leading '-' sign
+ ticks = -ticks;
+ if (ticks < 0)
+ {
+ Debug.Assert(ticks == long.MinValue /* -9223372036854775808 */);
+
+ // We computed these ahead of time; they're straight from the decimal representation of Int64.MinValue.
+ fraction = 4775808;
+ totalSecondsRemaining = 922337203685;
+ goto AfterComputeFraction;
+ }
+ }
+
+ totalSecondsRemaining = Math.DivRem((ulong)ticks, TimeSpan.TicksPerSecond, out ulong fraction64);
+ fraction = (uint)fraction64;
}
- int hours = (int)(time / TimeSpan.TicksPerHour % 24);
- int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
- int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
- int fraction = (int)(time % TimeSpan.TicksPerSecond);
- FormatLiterals literal;
- if (isInvariant)
+ AfterComputeFraction:
+ // Only write out the fraction if it's non-zero, and in that
+ // case write out the entire fraction (all digits).
+ Debug.Assert(fraction < 10_000_000);
+ int fractionDigits = 0;
+ switch (format)
{
- literal = value.Ticks < 0 ?
- NegativeInvariantFormatLiterals :
- PositiveInvariantFormatLiterals;
+ case StandardFormat.C:
+ // "c": Write out a fraction only if it's non-zero, and write out all 7 digits of it.
+ if (fraction != 0)
+ {
+ fractionDigits = DateTimeFormat.MaxSecondsFractionDigits;
+ requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
+ }
+ break;
+
+ case StandardFormat.G:
+ // "G": Write out a fraction regardless of whether it's 0, and write out all 7 digits of it.
+ fractionDigits = DateTimeFormat.MaxSecondsFractionDigits;
+ requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
+ break;
+
+ default:
+ // "g": Write out a fraction only if it's non-zero, and write out only the most significant digits.
+ Debug.Assert(format == StandardFormat.g);
+ if (fraction != 0)
+ {
+ fractionDigits = DateTimeFormat.MaxSecondsFractionDigits - FormattingHelpers.CountDecimalTrailingZeros(fraction, out fraction);
+ requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
+ }
+ break;
}
- else
+
+ ulong totalMinutesRemaining = 0, seconds = 0;
+ if (totalSecondsRemaining > 0)
{
- literal = new FormatLiterals();
- literal.Init(format, pattern == Pattern.Full);
+ // Only compute minutes if the TimeSpan has an absolute value of >= 1 minute.
+ totalMinutesRemaining = Math.DivRem(totalSecondsRemaining, 60 /* seconds per minute */, out seconds);
+ Debug.Assert(seconds < 60);
}
- if (fraction != 0)
+ ulong totalHoursRemaining = 0, minutes = 0;
+ if (totalMinutesRemaining > 0)
{
- // truncate the partial second to the specified length
- fraction = (int)(fraction / TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - literal.ff));
+ // Only compute hours if the TimeSpan has an absolute value of >= 1 hour.
+ totalHoursRemaining = Math.DivRem(totalMinutesRemaining, 60 /* minutes per hour */, out minutes);
+ Debug.Assert(minutes < 60);
}
- // Pattern.Full: [-]dd.hh:mm:ss.fffffff
- // Pattern.Minimum: [-][d.]hh:mm:ss[.fffffff]
+ // At this point, we can switch over to 32-bit DivRem since the data has shrunk far enough.
+ Debug.Assert(totalHoursRemaining <= uint.MaxValue);
- sb.Append(literal.Start); // [-]
- if (pattern == Pattern.Full || day != 0)
+ uint days = 0, hours = 0;
+ if (totalHoursRemaining > 0)
{
- sb.Append(day); // [dd]
- sb.Append(literal.DayHourSep); // [.]
- } //
- AppendNonNegativeInt32(sb, hours, literal.hh); // hh
- sb.Append(literal.HourMinuteSep); // :
- AppendNonNegativeInt32(sb, minutes, literal.mm); // mm
- sb.Append(literal.MinuteSecondSep); // :
- AppendNonNegativeInt32(sb, seconds, literal.ss); // ss
- if (!isInvariant && pattern == Pattern.Minimum)
+ // Only compute days if the TimeSpan has an absolute value of >= 1 day.
+ days = Math.DivRem((uint)totalHoursRemaining, 24 /* hours per day */, out hours);
+ Debug.Assert(hours < 24);
+ }
+
+ int hourDigits = 2;
+ if (format == StandardFormat.g && hours < 10)
+ {
+ // "g": Only writing a one-digit hour, rather than expected two-digit hour
+ hourDigits = 1;
+ requiredOutputLength--;
+ }
+
+ int dayDigits = 0;
+ if (days > 0)
+ {
+ dayDigits = FormattingHelpers.CountDigits(days);
+ Debug.Assert(dayDigits <= 8);
+ requiredOutputLength += dayDigits + 1; // for the leading "d."
+ }
+ else if (format == StandardFormat.G)
+ {
+ // "G": has a leading "0:" if days is 0
+ requiredOutputLength += 2;
+ dayDigits = 1;
+ }
+
+ if (destination.Length < requiredOutputLength)
{
- int effectiveDigits = literal.ff;
- while (effectiveDigits > 0)
+ charsWritten = 0;
+ return false;
+ }
+
+ // Write leading '-' if necessary
+ int idx = 0;
+ if (value.Ticks < 0)
+ {
+ destination[idx++] = '-';
+ }
+
+ // Write day and separator, if necessary
+ if (dayDigits != 0)
+ {
+ WriteDigits(days, destination.Slice(idx, dayDigits));
+ idx += dayDigits;
+ destination[idx++] = format == StandardFormat.C ? '.' : ':';
+ }
+
+ // Write "[h]h:mm:ss
+ Debug.Assert(hourDigits == 1 || hourDigits == 2);
+ if (hourDigits == 2)
+ {
+ WriteTwoDigits(hours, destination.Slice(idx));
+ idx += 2;
+ }
+ else
+ {
+ destination[idx++] = (char)('0' + hours);
+ }
+ destination[idx++] = ':';
+ WriteTwoDigits((uint)minutes, destination.Slice(idx));
+ idx += 2;
+ destination[idx++] = ':';
+ WriteTwoDigits((uint)seconds, destination.Slice(idx));
+ idx += 2;
+
+ // Write fraction and separator, if necessary
+ if (fractionDigits != 0)
+ {
+ if (format == StandardFormat.C)
{
- if (fraction % 10 == 0)
- {
- fraction = fraction / 10;
- effectiveDigits--;
- }
- else
- {
- break;
- }
+ destination[idx++] = '.';
}
- if (effectiveDigits > 0)
+ else if (decimalSeparator.Length == 1)
{
- sb.Append(literal.SecondFractionSep); // [.FFFFFFF]
- sb.Append((fraction).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ destination[idx++] = decimalSeparator[0];
}
+ else
+ {
+ decimalSeparator.AsSpan().CopyTo(destination);
+ idx += decimalSeparator.Length;
+ }
+ WriteDigits(fraction, destination.Slice(idx, fractionDigits));
+ idx += fractionDigits;
}
- else if (pattern == Pattern.Full || fraction != 0)
+
+ Debug.Assert(idx == requiredOutputLength);
+ charsWritten = requiredOutputLength;
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteTwoDigits(uint value, Span<char> buffer)
+ {
+ Debug.Assert(buffer.Length >= 2);
+ uint temp = '0' + value;
+ value /= 10;
+ buffer[1] = (char)(temp - (value * 10));
+ buffer[0] = (char)('0' + value);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteDigits(uint value, Span<char> buffer)
+ {
+ Debug.Assert(buffer.Length > 0);
+
+ for (int i = buffer.Length - 1; i >= 1; i--)
{
- sb.Append(literal.SecondFractionSep); // [.]
- AppendNonNegativeInt32(sb, fraction, literal.ff); // [fffffff]
+ uint temp = '0' + value;
+ value /= 10;
+ buffer[i] = (char)(temp - (value * 10));
}
- sb.Append(literal.End);
- return sb;
+ Debug.Assert(value < 10);
+ buffer[0] = (char)('0' + value);
}
/// <summary>Format the TimeSpan instance using the specified format.</summary>
- private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, StringBuilder result)
+ private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, StringBuilder result = null)
{
Debug.Assert(dtfi != null);
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
index ae77957ce..1bf81742a 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
@@ -62,15 +62,6 @@ namespace System.Globalization
private const int MaxSeconds = 59;
private const int MaxFraction = 9999999;
- private enum ParseFailureKind : byte
- {
- None = 0,
- ArgumentNull = 1,
- Format = 2,
- FormatWithParameter = 3,
- Overflow = 4,
- }
-
[Flags]
private enum TimeSpanStandardStyles : byte
{
@@ -99,11 +90,11 @@ namespace System.Globalization
internal int _zeroes; // Store the number of leading zeroes (if any)
internal ReadOnlySpan<char> _sep; // Store the literal that we are parsing (if any)
- public TimeSpanToken(TTT type) : this(type, 0, 0, default(ReadOnlySpan<char>)) { }
+ public TimeSpanToken(TTT type) : this(type, 0, 0, default) { }
- public TimeSpanToken(int number) : this(TTT.Num, number, 0, default(ReadOnlySpan<char>)) { }
+ public TimeSpanToken(int number) : this(TTT.Num, number, 0, default) { }
- public TimeSpanToken(int number, int leadingZeroes) : this(TTT.Num, number, leadingZeroes, default(ReadOnlySpan<char>)) { }
+ public TimeSpanToken(int number, int leadingZeroes) : this(TTT.Num, number, leadingZeroes, default) { }
public TimeSpanToken(TTT type, int number, int leadingZeroes, ReadOnlySpan<char> separator)
{
@@ -169,7 +160,7 @@ namespace System.Globalization
int digit;
if (++_pos >= _value.Length || (uint)(digit = _value[_pos] - '0') > 9)
{
- return new TimeSpanToken(TTT.Num, 0, zeroes, default(ReadOnlySpan<char>));
+ return new TimeSpanToken(TTT.Num, 0, zeroes, default);
}
if (digit == 0)
@@ -199,7 +190,7 @@ namespace System.Globalization
}
}
- return new TimeSpanToken(TTT.Num, num, zeroes, default(ReadOnlySpan<char>));
+ return new TimeSpanToken(TTT.Num, num, zeroes, default);
}
// Otherwise, we're processing a separator, and we've already processed the first
@@ -274,83 +265,83 @@ namespace System.Globalization
internal bool FullAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.AppCompatLiteral)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.AppCompatLiteral)
+ && _literals4.EqualsOrdinal(pattern.End);
internal bool PartialAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.AppCompatLiteral)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.AppCompatLiteral)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>DHMSF (all values matched)</summary>
internal bool FullMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == MaxLiteralTokens
&& _numCount == MaxNumericTokens
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals4, pattern.SecondFractionSep)
- && StringSpanHelpers.Equals(_literals5, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals4.EqualsOrdinal(pattern.SecondFractionSep)
+ && _literals5.EqualsOrdinal(pattern.End);
/// <summary>D (no hours, minutes, seconds, or fractions)</summary>
internal bool FullDMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 2
&& _numCount == 1
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.End);
/// <summary>HM (no days, seconds, or fractions)</summary>
internal bool FullHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 3
&& _numCount == 2
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.End);
/// <summary>DHM (no seconds or fraction)</summary>
internal bool FullDHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>HMS (no days or fraction)</summary>
internal bool FullHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>DHMS (no fraction)</summary>
internal bool FullDHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals4.EqualsOrdinal(pattern.End);
/// <summary>HMSF (no days)</summary>
internal bool FullHMSFMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals3, pattern.SecondFractionSep)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals3.EqualsOrdinal(pattern.SecondFractionSep)
+ && _literals4.EqualsOrdinal(pattern.End);
internal TTT _lastSeenTTT;
internal int _tokenCount;
@@ -391,7 +382,7 @@ namespace System.Globalization
switch (tok._ttt)
{
case TTT.Num:
- if ((_tokenCount == 0 && !AddSep(default(ReadOnlySpan<char>), ref result)) || !AddNum(tok, ref result))
+ if ((_tokenCount == 0 && !AddSep(default, ref result)) || !AddNum(tok, ref result))
{
return false;
}
@@ -405,11 +396,11 @@ namespace System.Globalization
break;
case TTT.NumOverflow:
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
default:
// Some unknown token or a repeat token type in the input
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
_lastSeenTTT = tok._ttt;
@@ -421,7 +412,7 @@ namespace System.Globalization
{
if (_sepCount >= MaxLiteralTokens || _tokenCount >= MaxTokens)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
switch (_sepCount++)
@@ -441,7 +432,7 @@ namespace System.Globalization
{
if (_numCount >= MaxNumericTokens || _tokenCount >= MaxTokens)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
switch (_numCount++)
@@ -459,41 +450,88 @@ namespace System.Globalization
}
/// <summary>Store the result of the parsing.</summary>
- private struct TimeSpanResult
+ private ref struct TimeSpanResult
{
internal TimeSpan parsedTimeSpan;
private readonly bool _throwOnFailure;
+ private readonly ReadOnlySpan<char> _originalTimeSpanString;
- internal TimeSpanResult(bool throwOnFailure)
+ internal TimeSpanResult(bool throwOnFailure, ReadOnlySpan<char> originalTimeSpanString)
{
- parsedTimeSpan = default(TimeSpan);
+ parsedTimeSpan = default;
_throwOnFailure = throwOnFailure;
+ _originalTimeSpanString = originalTimeSpanString;
}
- internal bool SetFailure(ParseFailureKind kind, string resourceKey, object messageArgument = null, string argumentName = null)
+ internal bool SetNoFormatSpecifierFailure()
{
if (!_throwOnFailure)
{
return false;
}
- string message = SR.GetResourceString(resourceKey);
- switch (kind)
+ throw new FormatException(SR.Format_NoFormatSpecifier);
+ }
+
+ internal bool SetBadQuoteFailure(char failingCharacter)
+ {
+ if (!_throwOnFailure)
{
- case ParseFailureKind.ArgumentNull:
- Debug.Assert(argumentName != null);
- throw new ArgumentNullException(argumentName, message);
+ return false;
+ }
- case ParseFailureKind.FormatWithParameter:
- throw new FormatException(SR.Format(message, messageArgument));
+ throw new FormatException(SR.Format(SR.Format_BadQuote, failingCharacter));
+ }
+
+ internal bool SetInvalidStringFailure()
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
- case ParseFailureKind.Overflow:
- throw new OverflowException(message);
+ throw new FormatException(SR.Format_InvalidString);
+ }
- default:
- Debug.Assert(kind == ParseFailureKind.Format, $"Unexpected failure {kind}");
- throw new FormatException(message);
+ internal bool SetArgumentNullFailure(string argumentName)
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
}
+
+ Debug.Assert(argumentName != null);
+ throw new ArgumentNullException(argumentName, SR.ArgumentNull_String);
+ }
+
+ internal bool SetOverflowFailure()
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ throw new OverflowException(SR.Format(SR.Overflow_TimeSpanElementTooLarge, new string(_originalTimeSpanString)));
+ }
+
+ internal bool SetBadTimeSpanFailure()
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ throw new FormatException(SR.Format(SR.Format_BadTimeSpan, new string(_originalTimeSpanString)));
+ }
+
+ internal bool SetBadFormatSpecifierFailure(char? formatSpecifierCharacter = null)
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ throw new FormatException(SR.Format(SR.Format_BadFormatSpecifier, formatSpecifierCharacter));
}
}
@@ -568,7 +606,7 @@ namespace System.Globalization
internal static TimeSpan Parse(ReadOnlySpan<char> input, IFormatProvider formatProvider)
{
- var parseResult = new TimeSpanResult(throwOnFailure: true);
+ var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
bool success = TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult);
Debug.Assert(success, "Should have thrown on failure");
return parseResult.parsedTimeSpan;
@@ -576,7 +614,7 @@ namespace System.Globalization
internal static bool TryParse(ReadOnlySpan<char> input, IFormatProvider formatProvider, out TimeSpan result)
{
- var parseResult = new TimeSpanResult(throwOnFailure: false);
+ var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult))
{
@@ -584,13 +622,13 @@ namespace System.Globalization
return true;
}
- result = default(TimeSpan);
+ result = default;
return false;
}
internal static TimeSpan ParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, TimeSpanStyles styles)
{
- var parseResult = new TimeSpanResult(throwOnFailure: true);
+ var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
bool success = TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult);
Debug.Assert(success, "Should have thrown on failure");
return parseResult.parsedTimeSpan;
@@ -598,7 +636,7 @@ namespace System.Globalization
internal static bool TryParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
- var parseResult = new TimeSpanResult(throwOnFailure: false);
+ var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult))
{
@@ -606,13 +644,13 @@ namespace System.Globalization
return true;
}
- result = default(TimeSpan);
+ result = default;
return false;
}
internal static TimeSpan ParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
{
- var parseResult = new TimeSpanResult(throwOnFailure: true);
+ var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
bool success = TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult);
Debug.Assert(success, "Should have thrown on failure");
return parseResult.parsedTimeSpan;
@@ -620,7 +658,7 @@ namespace System.Globalization
internal static bool TryParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
- var parseResult = new TimeSpanResult(throwOnFailure: false);
+ var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult))
{
@@ -628,7 +666,7 @@ namespace System.Globalization
return true;
}
- result = default(TimeSpan);
+ result = default;
return false;
}
@@ -638,7 +676,7 @@ namespace System.Globalization
input = input.Trim();
if (input.IsEmpty)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
var tokenizer = new TimeSpanTokenizer(input);
@@ -654,7 +692,7 @@ namespace System.Globalization
{
if (!raw.ProcessToken(ref tok, ref result))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
tok = tokenizer.GetNextToken();
}
@@ -662,7 +700,7 @@ namespace System.Globalization
if (!ProcessTerminalState(ref raw, style, ref result))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
return true;
@@ -691,7 +729,7 @@ namespace System.Globalization
tok._ttt = TTT.Sep;
if (!raw.ProcessToken(ref tok, ref result))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
}
@@ -702,7 +740,7 @@ namespace System.Globalization
case 3: return ProcessTerminal_HM_S_D(ref raw, style, ref result);
case 4: return ProcessTerminal_HMS_F_D(ref raw, style, ref result);
case 5: return ProcessTerminal_DHMSF(ref raw, style, ref result);
- default: return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ default: return result.SetBadTimeSpanFailure();
}
}
@@ -711,7 +749,7 @@ namespace System.Globalization
{
if (raw._sepCount != 6)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 5);
@@ -754,7 +792,7 @@ namespace System.Globalization
if (!TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, raw._numbers4, out ticks))
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
if (!positive)
@@ -762,15 +800,15 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
@@ -782,7 +820,7 @@ namespace System.Globalization
{
if (raw._sepCount != 5 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 4);
@@ -890,17 +928,17 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
return overflow ?
- result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge)) : // we found at least one literal pattern match but the numbers just didn't fit
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan)); // we couldn't find a thing
+ result.SetOverflowFailure() : // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetBadTimeSpanFailure(); // we couldn't find a thing
}
/// <summary>Validate the ambiguous 3-number "Hours:Minutes:Seconds", "Days.Hours:Minutes", or "Hours:Minutes:.Fraction" terminal case.</summary>
@@ -908,7 +946,7 @@ namespace System.Globalization
{
if (raw._sepCount != 4 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 3);
@@ -1016,17 +1054,17 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
return overflow ?
- result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge)) : // we found at least one literal pattern match but the numbers just didn't fit
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan)); // we couldn't find a thing
+ result.SetOverflowFailure() : // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetBadTimeSpanFailure(); // we couldn't find a thing
}
/// <summary>Validate the 2-number "Hours:Minutes" terminal case.</summary>
@@ -1034,7 +1072,7 @@ namespace System.Globalization
{
if (raw._sepCount != 3 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 2);
@@ -1080,7 +1118,7 @@ namespace System.Globalization
if (!TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, zero, out ticks))
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
if (!positive)
@@ -1088,15 +1126,15 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
/// <summary>Validate the 1-number "Days" terminal case.</summary>
@@ -1104,7 +1142,7 @@ namespace System.Globalization
{
if (raw._sepCount != 2 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 1);
@@ -1150,7 +1188,7 @@ namespace System.Globalization
if (!TryTimeToTicks(positive, raw._numbers0, zero, zero, zero, zero, out ticks))
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
if (!positive)
@@ -1158,15 +1196,15 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
/// <summary>Common private ParseExact method called by both ParseExact and TryParseExact.</summary>
@@ -1174,7 +1212,7 @@ namespace System.Globalization
{
if (format.Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetBadFormatSpecifierFailure();
}
if (format.Length == 1)
@@ -1193,7 +1231,7 @@ namespace System.Globalization
return TryParseTimeSpan(input, TimeSpanStandardStyles.Localized | TimeSpanStandardStyles.RequireFull, formatProvider, ref result);
default:
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetBadFormatSpecifierFailure(format[0]);
}
}
@@ -1230,7 +1268,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2 || seenHH || !ParseExactDigits(ref tokenizer, tokenLen, out hh))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenHH = true;
break;
@@ -1239,7 +1277,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2 || seenMM || !ParseExactDigits(ref tokenizer, tokenLen, out mm))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenMM = true;
break;
@@ -1248,7 +1286,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2 || seenSS || !ParseExactDigits(ref tokenizer, tokenLen, out ss))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenSS = true;
break;
@@ -1257,7 +1295,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF || !ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenFF = true;
break;
@@ -1266,7 +1304,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff);
seenFF = true;
@@ -1277,7 +1315,7 @@ namespace System.Globalization
int tmp = 0;
if (tokenLen > 8 || seenDD || !ParseExactDigits(ref tokenizer, (tokenLen < 2) ? 1 : tokenLen, (tokenLen < 2) ? 8 : tokenLen, out tmp, out dd))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenDD = true;
break;
@@ -1288,12 +1326,12 @@ namespace System.Globalization
if (!DateTimeParse.TryParseQuoteString(format, i, enquotedString, out tokenLen))
{
StringBuilderCache.Release(enquotedString);
- return result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadQuote), ch);
+ return result.SetBadQuoteFailure(ch);
}
if (!ParseExactLiteral(ref tokenizer, enquotedString))
{
StringBuilderCache.Release(enquotedString);
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
StringBuilderCache.Release(enquotedString);
break;
@@ -1315,7 +1353,7 @@ namespace System.Globalization
{
// This means that '%' is at the end of the format string or
// "%%" appears in the format string.
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
case '\\':
@@ -1330,12 +1368,12 @@ namespace System.Globalization
else
{
// This means that '\' is at the end of the format string or the literal match failed.
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
break;
default:
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
i += tokenLen;
@@ -1345,7 +1383,7 @@ namespace System.Globalization
if (!tokenizer.EOL)
{
// the custom format didn't consume the entire input
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
bool positive = (styles & TimeSpanStyles.AssumeNegative) == 0;
@@ -1361,12 +1399,12 @@ namespace System.Globalization
ticks = -ticks;
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
else
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
@@ -1456,7 +1494,7 @@ namespace System.Globalization
internal bool TryParse(ReadOnlySpan<char> input, ref TimeSpanResult result)
{
- result.parsedTimeSpan._ticks = 0;
+ result.parsedTimeSpan = default;
_str = input;
_len = input.Length;
@@ -1507,14 +1545,14 @@ namespace System.Globalization
// Allow -0 as well
if (time > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
else
{
if (time < 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
@@ -1522,10 +1560,10 @@ namespace System.Globalization
if (_pos < _len)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
- result.parsedTimeSpan._ticks = time;
+ result.parsedTimeSpan = new TimeSpan(time);
return true;
}
@@ -1537,13 +1575,13 @@ namespace System.Globalization
{
if ((i & 0xF0000000) != 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
i = i * 10 + _ch - '0';
if (i < 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
NextChar();
@@ -1551,12 +1589,12 @@ namespace System.Globalization
if (p == _pos)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
if (i > max)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
return true;
@@ -1575,7 +1613,7 @@ namespace System.Globalization
time = unit * TimeSpan.TicksPerHour;
if (_ch != ':')
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
NextChar();
@@ -1628,17 +1666,17 @@ namespace System.Globalization
{
if (formats == null)
{
- return result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), argumentName: nameof(formats));
+ return result.SetArgumentNullFailure(nameof(formats));
}
if (input.Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
if (formats.Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetNoFormatSpecifierFailure();
}
// Do a loop through the provided formats and see if we can parse succesfully in
@@ -1647,11 +1685,11 @@ namespace System.Globalization
{
if (formats[i] == null || formats[i].Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetBadFormatSpecifierFailure();
}
// Create a new non-throwing result each time to ensure the runs are independent.
- TimeSpanResult innerResult = new TimeSpanResult(throwOnFailure: false);
+ TimeSpanResult innerResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseExactTimeSpan(input, formats[i], formatProvider, styles, ref innerResult))
{
@@ -1660,7 +1698,7 @@ namespace System.Globalization
}
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
index 21a938f8f..777af1800 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
@@ -355,7 +355,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
minDate,
@@ -378,7 +378,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinCalendarYear,
@@ -510,7 +510,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -710,7 +710,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -774,7 +774,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -814,7 +814,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(value),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinCalendarYear,
@@ -845,7 +845,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinCalendarYear,
diff --git a/src/System.Private.CoreLib/shared/System/Guid.Unix.cs b/src/System.Private.CoreLib/shared/System/Guid.Unix.cs
new file mode 100644
index 000000000..442e7f883
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Guid.Unix.cs
@@ -0,0 +1,38 @@
+// 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.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ partial struct Guid
+ {
+ // This will create a new random guid based on the https://www.ietf.org/rfc/rfc4122.txt
+ public static unsafe Guid NewGuid()
+ {
+ Guid g;
+ Interop.GetRandomBytes((byte*)&g, sizeof(Guid));
+
+ const ushort VersionMask = 0xF000;
+ const ushort RandomGuidVersion = 0x4000;
+
+ const byte ClockSeqHiAndReservedMask = 0xC0;
+ const byte ClockSeqHiAndReservedValue = 0x80;
+
+ // Modify bits indicating the type of the GUID
+
+ unchecked
+ {
+ // time_hi_and_version
+ g._c = (short)((g._c & ~VersionMask) | RandomGuidVersion);
+ // clock_seq_hi_and_reserved
+ g._d = (byte)((g._d & ~ClockSeqHiAndReservedMask) | ClockSeqHiAndReservedValue);
+ }
+
+ return g;
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/System/Guid.Windows.cs b/src/System.Private.CoreLib/shared/System/Guid.Windows.cs
new file mode 100644
index 000000000..6a275084f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Guid.Windows.cs
@@ -0,0 +1,29 @@
+// 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.
+
+namespace System
+{
+ partial struct Guid
+ {
+ public static Guid NewGuid()
+ {
+ // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some
+ // uniqueness guarantees.
+
+ Guid g;
+ int hr = Interop.Ole32.CoCreateGuid(out g);
+ // We don't expect that this will ever throw an error, none are even documented, and so we don't want to pull
+ // in the HR to ComException mappings into the core library just for this so we will try a generic exception if
+ // we ever hit this condition.
+ if (hr != 0)
+ {
+ Exception ex = new Exception();
+ ex.HResult = hr;
+ throw ex;
+ }
+ return g;
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/System/Guid.cs b/src/System.Private.CoreLib/shared/System/Guid.cs
index 423d5bc78..6e6ec067a 100644
--- a/src/System.Private.CoreLib/shared/System/Guid.cs
+++ b/src/System.Private.CoreLib/shared/System/Guid.cs
@@ -279,7 +279,7 @@ namespace System
{
if (input == null)
{
- result = default(Guid);
+ result = default;
return false;
}
@@ -297,7 +297,7 @@ namespace System
}
else
{
- result = default(Guid);
+ result = default;
return false;
}
}
@@ -358,7 +358,7 @@ namespace System
{
if (input == null)
{
- result = default(Guid);
+ result = default;
return false;
}
@@ -369,7 +369,7 @@ namespace System
{
if (format.Length != 1)
{
- result = default(Guid);
+ result = default;
return false;
}
@@ -398,7 +398,7 @@ namespace System
break;
default:
// invalid guid format specification
- result = default(Guid);
+ result = default;
return false;
}
@@ -411,7 +411,7 @@ namespace System
}
else
{
- result = default(Guid);
+ result = default;
return false;
}
}
@@ -427,7 +427,7 @@ namespace System
}
// Check for dashes
- bool dashesExistInString = guidString.IndexOf('-') >= 0;
+ bool dashesExistInString = guidString.Contains('-');
if (dashesExistInString)
{
@@ -449,7 +449,7 @@ namespace System
}
// Check for braces
- bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0);
+ bool bracesExistInString = guidString.Contains('{');
if (bracesExistInString)
{
@@ -471,7 +471,7 @@ namespace System
}
// Check for parenthesis
- bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0);
+ bool parenthesisExistInString = guidString.Contains('(');
if (parenthesisExistInString)
{
@@ -548,7 +548,7 @@ namespace System
// Find the end of this hex number (since it is not fixed length)
numStart = 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -566,7 +566,7 @@ namespace System
}
// +3 to get by ',0x'
numStart = numStart + numLen + 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -584,7 +584,7 @@ namespace System
}
// +3 to get by ',0x'
numStart = numStart + numLen + 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -621,7 +621,7 @@ namespace System
// Calculate number length
if (i < 7) // first 7 cases
{
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -630,7 +630,7 @@ namespace System
}
else // last case ends with '}', not ','
{
- numLen = guidString.IndexOf('}', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf('}');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidBraceAfterLastNumber));
@@ -1232,7 +1232,7 @@ namespace System
return (char)((a > 9) ? a - 10 + 0x61 : a + 0x30);
}
- unsafe private static int HexsToChars(char* guidChars, int a, int b)
+ private static unsafe int HexsToChars(char* guidChars, int a, int b)
{
guidChars[0] = HexToChar(a >> 4);
guidChars[1] = HexToChar(a);
@@ -1243,7 +1243,7 @@ namespace System
return 4;
}
- unsafe private static int HexsToCharsHexOutput(char* guidChars, int a, int b)
+ private static unsafe int HexsToCharsHexOutput(char* guidChars, int a, int b)
{
guidChars[0] = '0';
guidChars[1] = 'x';
diff --git a/src/System.Private.CoreLib/shared/System/HResults.cs b/src/System.Private.CoreLib/shared/System/HResults.cs
index ffc47d85b..4a5ec0d63 100644
--- a/src/System.Private.CoreLib/shared/System/HResults.cs
+++ b/src/System.Private.CoreLib/shared/System/HResults.cs
@@ -25,6 +25,7 @@ namespace System
{
internal static partial class HResults
{
+ internal const int S_OK = unchecked((int)0x00000000);
internal const int COR_E_ABANDONEDMUTEX = unchecked((int)0x8013152D);
internal const int COR_E_AMBIGUOUSMATCH = unchecked((int)0x8000211D);
internal const int COR_E_APPDOMAINUNLOADED = unchecked((int)0x80131014);
@@ -122,5 +123,7 @@ namespace System
internal const int ERROR_MRM_MAP_NOT_FOUND = unchecked((int)0x80073B1F);
internal const int RO_E_CLOSED = unchecked((int)0x80000013);
internal const int TYPE_E_TYPEMISMATCH = unchecked((int)0x80028CA0);
+ internal const int CO_E_NOTINITIALIZED = unchecked((int)0x800401F0);
+ internal const int RPC_E_CHANGED_MODE = unchecked((int)0x80010106);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IAsyncResult.cs b/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
index 0abeaca52..56ebcdb2f 100644
--- a/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
+++ b/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
@@ -23,7 +23,7 @@ namespace System
WaitHandle AsyncWaitHandle { get; }
- Object AsyncState { get; }
+ object AsyncState { get; }
bool CompletedSynchronously { get; }
}
diff --git a/src/System.Private.CoreLib/shared/System/IComparable.cs b/src/System.Private.CoreLib/shared/System/IComparable.cs
index 72aeeb027..cf71953e2 100644
--- a/src/System.Private.CoreLib/shared/System/IComparable.cs
+++ b/src/System.Private.CoreLib/shared/System/IComparable.cs
@@ -18,7 +18,7 @@ namespace System
// if this is equal to object, or a value greater than zero
// if this is greater than object.
//
- int CompareTo(Object obj);
+ int CompareTo(object obj);
}
// Generic version of IComparable.
diff --git a/src/System.Private.CoreLib/shared/System/IConvertible.cs b/src/System.Private.CoreLib/shared/System/IConvertible.cs
index 87351127f..7abd0c45c 100644
--- a/src/System.Private.CoreLib/shared/System/IConvertible.cs
+++ b/src/System.Private.CoreLib/shared/System/IConvertible.cs
@@ -54,10 +54,10 @@ namespace System
ulong ToUInt64(IFormatProvider provider);
float ToSingle(IFormatProvider provider);
double ToDouble(IFormatProvider provider);
- Decimal ToDecimal(IFormatProvider provider);
+ decimal ToDecimal(IFormatProvider provider);
DateTime ToDateTime(IFormatProvider provider);
- String ToString(IFormatProvider provider);
- Object ToType(Type conversionType, IFormatProvider provider);
+ string ToString(IFormatProvider provider);
+ object ToType(Type conversionType, IFormatProvider provider);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs b/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs
index 47340f309..cd798b4a1 100644
--- a/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs
+++ b/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs
@@ -19,6 +19,6 @@ namespace System
public interface ICustomFormatter
{
// Interface does not need to be marked with the serializable attribute
- String Format(String format, Object arg, IFormatProvider formatProvider);
+ string Format(string format, object arg, IFormatProvider formatProvider);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IFormatProvider.cs b/src/System.Private.CoreLib/shared/System/IFormatProvider.cs
index 0c17354af..9369b074f 100644
--- a/src/System.Private.CoreLib/shared/System/IFormatProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/IFormatProvider.cs
@@ -18,6 +18,6 @@ namespace System
public interface IFormatProvider
{
// Interface does not need to be marked with the serializable attribute
- Object GetFormat(Type formatType);
+ object GetFormat(Type formatType);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IFormattable.cs b/src/System.Private.CoreLib/shared/System/IFormattable.cs
index 1f2f7022c..b5ed9bb45 100644
--- a/src/System.Private.CoreLib/shared/System/IFormattable.cs
+++ b/src/System.Private.CoreLib/shared/System/IFormattable.cs
@@ -8,6 +8,6 @@ namespace System
{
public interface IFormattable
{
- String ToString(String format, IFormatProvider formatProvider);
+ string ToString(string format, IFormatProvider formatProvider);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs
new file mode 100644
index 000000000..1f1b9218f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs
@@ -0,0 +1,717 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Wraps a stream and provides convenient read functionality
+** for strings and primitive types.
+**
+**
+============================================================*/
+
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace System.IO
+{
+ public class BinaryReader : IDisposable
+ {
+ private const int MaxCharBytesSize = 128;
+
+ private Stream _stream;
+ private byte[] _buffer;
+ private Decoder _decoder;
+ private byte[] _charBytes;
+ private char[] _singleChar;
+ private char[] _charBuffer;
+ private int _maxCharsSize; // From MaxCharBytesSize & Encoding
+
+ // Performance optimization for Read() w/ Unicode. Speeds us up by ~40%
+ private bool _2BytesPerChar;
+ private bool _isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf
+ private bool _leaveOpen;
+
+ public BinaryReader(Stream input) : this(input, Encoding.UTF8, false)
+ {
+ }
+
+ public BinaryReader(Stream input, Encoding encoding) : this(input, encoding, false)
+ {
+ }
+
+ public BinaryReader(Stream input, Encoding encoding, bool leaveOpen)
+ {
+ if (input == null)
+ {
+ throw new ArgumentNullException(nameof(input));
+ }
+ if (encoding == null)
+ {
+ throw new ArgumentNullException(nameof(encoding));
+ }
+ if (!input.CanRead)
+ {
+ throw new ArgumentException(SR.Argument_StreamNotReadable);
+ }
+
+ _stream = input;
+ _decoder = encoding.GetDecoder();
+ _maxCharsSize = encoding.GetMaxCharCount(MaxCharBytesSize);
+ int minBufferSize = encoding.GetMaxByteCount(1); // max bytes per one char
+ if (minBufferSize < 16)
+ {
+ minBufferSize = 16;
+ }
+
+ _buffer = new byte[minBufferSize];
+ // _charBuffer and _charBytes will be left null.
+
+ // For Encodings that always use 2 bytes per char (or more),
+ // special case them here to make Read() & Peek() faster.
+ _2BytesPerChar = encoding is UnicodeEncoding;
+ // check if BinaryReader is based on MemoryStream, and keep this for it's life
+ // we cannot use "as" operator, since derived classes are not allowed
+ _isMemoryStream = (_stream.GetType() == typeof(MemoryStream));
+ _leaveOpen = leaveOpen;
+
+ Debug.Assert(_decoder != null, "[BinaryReader.ctor]_decoder!=null");
+ }
+
+ public virtual Stream BaseStream
+ {
+ get
+ {
+ return _stream;
+ }
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Stream copyOfStream = _stream;
+ _stream = null;
+ if (copyOfStream != null && !_leaveOpen)
+ {
+ copyOfStream.Close();
+ }
+ }
+ _stream = null;
+ _buffer = null;
+ _decoder = null;
+ _charBytes = null;
+ _singleChar = null;
+ _charBuffer = null;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ /// <remarks>
+ /// Override Dispose(bool) instead of Close(). This API exists for compatibility purposes.
+ /// </remarks>
+ public virtual void Close()
+ {
+ Dispose(true);
+ }
+
+ public virtual int PeekChar()
+ {
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ if (!_stream.CanSeek)
+ {
+ return -1;
+ }
+
+ long origPos = _stream.Position;
+ int ch = Read();
+ _stream.Position = origPos;
+ return ch;
+ }
+
+ public virtual int Read()
+ {
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ int charsRead = 0;
+ int numBytes = 0;
+ long posSav = posSav = 0;
+
+ if (_stream.CanSeek)
+ {
+ posSav = _stream.Position;
+ }
+
+ if (_charBytes == null)
+ {
+ _charBytes = new byte[MaxCharBytesSize]; //REVIEW: We need at most 2 bytes/char here?
+ }
+ if (_singleChar == null)
+ {
+ _singleChar = new char[1];
+ }
+
+ while (charsRead == 0)
+ {
+ // We really want to know what the minimum number of bytes per char
+ // is for our encoding. Otherwise for UnicodeEncoding we'd have to
+ // do ~1+log(n) reads to read n characters.
+ // Assume 1 byte can be 1 char unless _2BytesPerChar is true.
+ numBytes = _2BytesPerChar ? 2 : 1;
+
+ int r = _stream.ReadByte();
+ _charBytes[0] = (byte)r;
+ if (r == -1)
+ {
+ numBytes = 0;
+ }
+ if (numBytes == 2)
+ {
+ r = _stream.ReadByte();
+ _charBytes[1] = (byte)r;
+ if (r == -1)
+ {
+ numBytes = 1;
+ }
+ }
+
+ if (numBytes == 0)
+ {
+ return -1;
+ }
+
+ Debug.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::ReadOneChar assumes it's reading one or 2 bytes only.");
+
+ try
+ {
+ charsRead = _decoder.GetChars(_charBytes, 0, numBytes, _singleChar, 0);
+ }
+ catch
+ {
+ // Handle surrogate char
+
+ if (_stream.CanSeek)
+ {
+ _stream.Seek((posSav - _stream.Position), SeekOrigin.Current);
+ }
+ // else - we can't do much here
+
+ throw;
+ }
+
+ Debug.Assert(charsRead < 2, "BinaryReader::ReadOneChar - assuming we only got 0 or 1 char, not 2!");
+ }
+ Debug.Assert(charsRead > 0);
+ return _singleChar[0];
+ }
+
+ public virtual bool ReadBoolean()
+ {
+ FillBuffer(1);
+ return (_buffer[0] != 0);
+ }
+
+ public virtual byte ReadByte()
+ {
+ // Inlined to avoid some method call overhead with FillBuffer.
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ int b = _stream.ReadByte();
+ if (b == -1)
+ {
+ throw Error.GetEndOfFile();
+ }
+
+ return (byte)b;
+ }
+
+ [CLSCompliant(false)]
+ public virtual sbyte ReadSByte()
+ {
+ FillBuffer(1);
+ return (sbyte)(_buffer[0]);
+ }
+
+ public virtual char ReadChar()
+ {
+ int value = Read();
+ if (value == -1)
+ {
+ throw Error.GetEndOfFile();
+ }
+ return (char)value;
+ }
+
+ public virtual short ReadInt16()
+ {
+ FillBuffer(2);
+ return (short)(_buffer[0] | _buffer[1] << 8);
+ }
+
+ [CLSCompliant(false)]
+ public virtual ushort ReadUInt16()
+ {
+ FillBuffer(2);
+ return (ushort)(_buffer[0] | _buffer[1] << 8);
+ }
+
+ public virtual int ReadInt32()
+ {
+ if (_isMemoryStream)
+ {
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ // read directly from MemoryStream buffer
+ MemoryStream mStream = _stream as MemoryStream;
+ Debug.Assert(mStream != null, "_stream as MemoryStream != null");
+
+ return mStream.InternalReadInt32();
+ }
+ else
+ {
+ FillBuffer(4);
+ return (int)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
+ }
+ }
+
+ [CLSCompliant(false)]
+ public virtual uint ReadUInt32()
+ {
+ FillBuffer(4);
+ return (uint)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
+ }
+
+ public virtual long ReadInt64()
+ {
+ FillBuffer(8);
+ uint lo = (uint)(_buffer[0] | _buffer[1] << 8 |
+ _buffer[2] << 16 | _buffer[3] << 24);
+ uint hi = (uint)(_buffer[4] | _buffer[5] << 8 |
+ _buffer[6] << 16 | _buffer[7] << 24);
+ return (long)((ulong)hi) << 32 | lo;
+ }
+
+ [CLSCompliant(false)]
+ public virtual ulong ReadUInt64()
+ {
+ FillBuffer(8);
+ uint lo = (uint)(_buffer[0] | _buffer[1] << 8 |
+ _buffer[2] << 16 | _buffer[3] << 24);
+ uint hi = (uint)(_buffer[4] | _buffer[5] << 8 |
+ _buffer[6] << 16 | _buffer[7] << 24);
+ return ((ulong)hi) << 32 | lo;
+ }
+
+ public virtual unsafe float ReadSingle()
+ {
+ FillBuffer(4);
+ uint tmpBuffer = (uint)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
+ return *((float*)&tmpBuffer);
+ }
+
+ public virtual unsafe double ReadDouble()
+ {
+ FillBuffer(8);
+ uint lo = (uint)(_buffer[0] | _buffer[1] << 8 |
+ _buffer[2] << 16 | _buffer[3] << 24);
+ uint hi = (uint)(_buffer[4] | _buffer[5] << 8 |
+ _buffer[6] << 16 | _buffer[7] << 24);
+
+ ulong tmpBuffer = ((ulong)hi) << 32 | lo;
+ return *((double*)&tmpBuffer);
+ }
+
+ public virtual decimal ReadDecimal()
+ {
+ FillBuffer(16);
+ try
+ {
+ return decimal.ToDecimal(_buffer);
+ }
+ catch (ArgumentException e)
+ {
+ // ReadDecimal cannot leak out ArgumentException
+ throw new IOException(SR.Arg_DecBitCtor, e);
+ }
+ }
+
+ public virtual string ReadString()
+ {
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ int currPos = 0;
+ int n;
+ int stringLength;
+ int readLength;
+ int charsRead;
+
+ // Length of the string in bytes, not chars
+ stringLength = Read7BitEncodedInt();
+ if (stringLength < 0)
+ {
+ throw new IOException(SR.Format(SR.IO_InvalidStringLen_Len, stringLength));
+ }
+
+ if (stringLength == 0)
+ {
+ return string.Empty;
+ }
+
+ if (_charBytes == null)
+ {
+ _charBytes = new byte[MaxCharBytesSize];
+ }
+
+ if (_charBuffer == null)
+ {
+ _charBuffer = new char[_maxCharsSize];
+ }
+
+ StringBuilder sb = null;
+ do
+ {
+ readLength = ((stringLength - currPos) > MaxCharBytesSize) ? MaxCharBytesSize : (stringLength - currPos);
+
+ n = _stream.Read(_charBytes, 0, readLength);
+ if (n == 0)
+ {
+ throw Error.GetEndOfFile();
+ }
+
+ charsRead = _decoder.GetChars(_charBytes, 0, n, _charBuffer, 0);
+
+ if (currPos == 0 && n == stringLength)
+ {
+ return new string(_charBuffer, 0, charsRead);
+ }
+
+ if (sb == null)
+ {
+ sb = StringBuilderCache.Acquire(stringLength); // Actual string length in chars may be smaller.
+ }
+
+ sb.Append(_charBuffer, 0, charsRead);
+ currPos += n;
+ } while (currPos < stringLength);
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ public virtual int Read(char[] buffer, int index, int count)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
+ }
+ if (index < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ if (buffer.Length - index < count)
+ {
+ throw new ArgumentException(SR.Argument_InvalidOffLen);
+ }
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ // SafeCritical: index and count have already been verified to be a valid range for the buffer
+ return InternalReadChars(new Span<char>(buffer, index, count));
+ }
+
+ public virtual int Read(Span<char> buffer)
+ {
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ return InternalReadChars(buffer);
+ }
+
+ private int InternalReadChars(Span<char> buffer)
+ {
+ Debug.Assert(_stream != null);
+
+ int numBytes = 0;
+ int index = 0;
+ int charsRemaining = buffer.Length;
+
+ if (_charBytes == null)
+ {
+ _charBytes = new byte[MaxCharBytesSize];
+ }
+
+ while (charsRemaining > 0)
+ {
+ int charsRead = 0;
+ // We really want to know what the minimum number of bytes per char
+ // is for our encoding. Otherwise for UnicodeEncoding we'd have to
+ // do ~1+log(n) reads to read n characters.
+ numBytes = charsRemaining;
+
+ if (_2BytesPerChar)
+ {
+ numBytes <<= 1;
+ }
+ if (numBytes > MaxCharBytesSize)
+ {
+ numBytes = MaxCharBytesSize;
+ }
+
+ int position = 0;
+ byte[] byteBuffer = null;
+ if (_isMemoryStream)
+ {
+ MemoryStream mStream = _stream as MemoryStream;
+ Debug.Assert(mStream != null, "_stream as MemoryStream != null");
+
+ position = mStream.InternalGetPosition();
+ numBytes = mStream.InternalEmulateRead(numBytes);
+ byteBuffer = mStream.InternalGetBuffer();
+ }
+ else
+ {
+ numBytes = _stream.Read(_charBytes, 0, numBytes);
+ byteBuffer = _charBytes;
+ }
+
+ if (numBytes == 0)
+ {
+ return (buffer.Length - charsRemaining);
+ }
+
+ Debug.Assert(byteBuffer != null, "expected byteBuffer to be non-null");
+ checked
+ {
+ if (position < 0 || numBytes < 0 || position > byteBuffer.Length - numBytes)
+ {
+ throw new ArgumentOutOfRangeException(nameof(numBytes));
+ }
+ if (index < 0 || charsRemaining < 0 || index > buffer.Length - charsRemaining)
+ {
+ throw new ArgumentOutOfRangeException(nameof(charsRemaining));
+ }
+ unsafe
+ {
+ fixed (byte* pBytes = byteBuffer)
+ fixed (char* pChars = &MemoryMarshal.GetReference(buffer))
+ {
+ charsRead = _decoder.GetChars(pBytes + position, numBytes, pChars + index, charsRemaining, flush: false);
+ }
+ }
+ }
+
+ charsRemaining -= charsRead;
+ index += charsRead;
+ }
+
+ // this should never fail
+ Debug.Assert(charsRemaining >= 0, "We read too many characters.");
+
+ // we may have read fewer than the number of characters requested if end of stream reached
+ // or if the encoding makes the char count too big for the buffer (e.g. fallback sequence)
+ return (buffer.Length - charsRemaining);
+ }
+
+ public virtual char[] ReadChars(int count)
+ {
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ if (count == 0)
+ {
+ return Array.Empty<char>();
+ }
+
+ // SafeCritical: we own the chars buffer, and therefore can guarantee that the index and count are valid
+ char[] chars = new char[count];
+ int n = InternalReadChars(new Span<char>(chars));
+ if (n != count)
+ {
+ char[] copy = new char[n];
+ Buffer.BlockCopy(chars, 0, copy, 0, 2 * n); // sizeof(char)
+ chars = copy;
+ }
+
+ return chars;
+ }
+
+ public virtual int Read(byte[] buffer, int index, int count)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
+ }
+ if (index < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ if (buffer.Length - index < count)
+ {
+ throw new ArgumentException(SR.Argument_InvalidOffLen);
+ }
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ return _stream.Read(buffer, index, count);
+ }
+
+ public virtual int Read(Span<byte> buffer)
+ {
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ return _stream.Read(buffer);
+ }
+
+ public virtual byte[] ReadBytes(int count)
+ {
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ if (_stream == null)
+ {
+ throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ }
+
+ if (count == 0)
+ {
+ return Array.Empty<byte>();
+ }
+
+ byte[] result = new byte[count];
+ int numRead = 0;
+ do
+ {
+ int n = _stream.Read(result, numRead, count);
+ if (n == 0)
+ {
+ break;
+ }
+
+ numRead += n;
+ count -= n;
+ } while (count > 0);
+
+ if (numRead != result.Length)
+ {
+ // Trim array. This should happen on EOF & possibly net streams.
+ byte[] copy = new byte[numRead];
+ Buffer.BlockCopy(result, 0, copy, 0, numRead);
+ result = copy;
+ }
+
+ return result;
+ }
+
+ protected virtual void FillBuffer(int numBytes)
+ {
+ if (_buffer != null && (numBytes < 0 || numBytes > _buffer.Length))
+ {
+ throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_BinaryReaderFillBuffer);
+ }
+
+ int bytesRead = 0;
+ int n = 0;
+
+ if (_stream == null)
+ {
+ throw Error.GetFileNotOpen();
+ }
+
+ // Need to find a good threshold for calling ReadByte() repeatedly
+ // vs. calling Read(byte[], int, int) for both buffered & unbuffered
+ // streams.
+ if (numBytes == 1)
+ {
+ n = _stream.ReadByte();
+ if (n == -1)
+ {
+ throw Error.GetEndOfFile();
+ }
+
+ _buffer[0] = (byte)n;
+ return;
+ }
+
+ do
+ {
+ n = _stream.Read(_buffer, bytesRead, numBytes - bytesRead);
+ if (n == 0)
+ {
+ throw Error.GetEndOfFile();
+ }
+ bytesRead += n;
+ } while (bytesRead < numBytes);
+ }
+
+ protected internal int Read7BitEncodedInt()
+ {
+ // Read out an Int32 7 bits at a time. The high bit
+ // of the byte when on means to continue reading more bytes.
+ int count = 0;
+ int shift = 0;
+ byte b;
+ do
+ {
+ // Check for a corrupted stream. Read a max of 5 bytes.
+ // In a future version, add a DataFormatException.
+ if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7
+ {
+ throw new FormatException(SR.Format_Bad7BitInt32);
+ }
+
+ // ReadByte handles end of stream cases for us.
+ b = ReadByte();
+ count |= (b & 0x7F) << shift;
+ shift += 7;
+ } while ((b & 0x80) != 0);
+ return count;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs
index ad1d31f57..d1a333f41 100644
--- a/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs
@@ -166,7 +166,7 @@ namespace System.IO
//
public unsafe virtual void Write(char ch)
{
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
throw new ArgumentException(SR.Arg_SurrogatesNotAllowedAsSingleChar);
Debug.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)");
@@ -223,7 +223,7 @@ namespace System.IO
public virtual void Write(decimal value)
{
- Decimal.GetBytes(value, _buffer);
+ decimal.GetBytes(value, _buffer);
OutStream.Write(_buffer, 0, 16);
}
@@ -325,7 +325,7 @@ namespace System.IO
// a four-byte unsigned integer, and then writes that many characters
// to the stream.
//
- public unsafe virtual void Write(String value)
+ public unsafe virtual void Write(string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
diff --git a/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs b/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs
index aa10e8d88..a3a2d2983 100644
--- a/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs
@@ -2,7 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#if MS_IO_REDIST
+using System;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
/// <summary>
/// Simple wrapper to safely disable the normal media insertion prompt for
diff --git a/src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs b/src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs
deleted file mode 100644
index 3f2c88c74..000000000
--- a/src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.Runtime.Serialization;
-
-namespace System.IO
-{
- //Thrown when trying to access a drive that is not available.
- [Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- internal class DriveNotFoundException : IOException
- {
- public DriveNotFoundException()
- : base(SR.Arg_DriveNotFoundException)
- {
- HResult = HResults.COR_E_DIRECTORYNOTFOUND;
- }
-
- public DriveNotFoundException(string message)
- : base(message)
- {
- HResult = HResults.COR_E_DIRECTORYNOTFOUND;
- }
-
- public DriveNotFoundException(string message, Exception innerException)
- : base(message, innerException)
- {
- HResult = HResults.COR_E_DIRECTORYNOTFOUND;
- }
-
- protected DriveNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
index d9fcf6571..ae4b709ea 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
@@ -61,10 +61,12 @@ namespace System.IO
return SafeFileHandle.Open(_path, openFlags, (int)OpenPermissions);
}
+ private static bool GetDefaultIsAsync(SafeFileHandle handle) => handle.IsAsync ?? DefaultIsAsync;
+
/// <summary>Initializes a stream for reading or writing a Unix file.</summary>
/// <param name="mode">How the file should be opened.</param>
/// <param name="share">What other access to the file should be allowed. This is currently ignored.</param>
- private void Init(FileMode mode, FileShare share)
+ private void Init(FileMode mode, FileShare share, string originalPath)
{
_fileHandle.IsAsync = _useAsyncIO;
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
index 4b75ad6da..edcf8e546 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
@@ -2,6 +2,7 @@
// 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.Diagnostics;
using Microsoft.Win32.SafeHandles;
namespace System.IO
@@ -43,5 +44,62 @@ namespace System.IO
Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero));
}
}
+
+ private static bool GetDefaultIsAsync(SafeFileHandle handle)
+ {
+ return handle.IsAsync ?? !IsHandleSynchronous(handle, ignoreInvalid: true) ?? DefaultIsAsync;
+ }
+
+ private static unsafe bool? IsHandleSynchronous(SafeFileHandle fileHandle, bool ignoreInvalid)
+ {
+ if (fileHandle.IsInvalid)
+ return null;
+
+ uint fileMode;
+
+ int status = Interop.NtDll.NtQueryInformationFile(
+ FileHandle: fileHandle,
+ IoStatusBlock: out Interop.NtDll.IO_STATUS_BLOCK ioStatus,
+ FileInformation: &fileMode,
+ Length: sizeof(uint),
+ FileInformationClass: Interop.NtDll.FileModeInformation);
+
+ switch (status)
+ {
+ case 0:
+ // We we're successful
+ break;
+ case Interop.NtDll.STATUS_INVALID_HANDLE:
+ if (!ignoreInvalid)
+ {
+ throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_INVALID_HANDLE);
+ }
+ else
+ {
+ return null;
+ }
+ default:
+ // Something else is preventing access
+ Debug.Fail("Unable to get the file mode information, status was" + status.ToString());
+ return null;
+ }
+
+ // If either of these two flags are set, the file handle is synchronous (not overlapped)
+ return (fileMode & (Interop.NtDll.FILE_SYNCHRONOUS_IO_ALERT | Interop.NtDll.FILE_SYNCHRONOUS_IO_NONALERT)) > 0;
+ }
+
+ private static void VerifyHandleIsSync(SafeFileHandle handle, int fileType, FileAccess access)
+ {
+ // As we can accurately check the handle type when we have access to NtQueryInformationFile we don't need to skip for
+ // any particular file handle type.
+
+ // If the handle was passed in without an explicit async setting, we already looked it up in GetDefaultIsAsync
+ if (!handle.IsAsync.HasValue)
+ return;
+
+ // If we can't check the handle, just assume it is ok.
+ if (!(IsHandleSynchronous(handle, ignoreInvalid: false) ?? true))
+ throw new ArgumentException(SR.Arg_HandleNotSync, nameof(handle));
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs
index 304088eea..b326525a7 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs
@@ -40,5 +40,58 @@ namespace System.IO
pCreateExParams: ref parameters));
}
}
+
+ private static bool GetDefaultIsAsync(SafeFileHandle handle) => handle.IsAsync ?? DefaultIsAsync;
+
+ private static unsafe bool? IsHandleSynchronous(SafeFileHandle handle, FileAccess access)
+ {
+ // Do NOT use this method on any type other than DISK. Reading or writing to a pipe may
+ // cause an app to block incorrectly, introducing a deadlock (depending on whether a write
+ // will wake up an already-blocked thread or this Win32FileStream's thread).
+
+ byte* bytes = stackalloc byte[1];
+ int numBytesReadWritten;
+ int r = -1;
+
+ // If the handle is a pipe, ReadFile will block until there
+ // has been a write on the other end. We'll just have to deal with it,
+ // For the read end of a pipe, you can mess up and
+ // accidentally read synchronously from an async pipe.
+ if ((access & FileAccess.Read) != 0)
+ {
+ r = Interop.Kernel32.ReadFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
+ }
+ else if ((access & FileAccess.Write) != 0)
+ {
+ r = Interop.Kernel32.WriteFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
+ }
+
+ if (r == 0)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ switch (errorCode)
+ {
+ case Interop.Errors.ERROR_INVALID_PARAMETER:
+ return false;
+ case Interop.Errors.ERROR_INVALID_HANDLE:
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ }
+ }
+
+ return true;
+ }
+
+ private static void VerifyHandleIsSync(SafeFileHandle handle, int fileType, FileAccess access)
+ {
+ // The technique here only really works for FILE_TYPE_DISK. FileMode is the right thing to check, but it currently
+ // isn't available in WinRT.
+
+ if (fileType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
+ {
+ // If we can't check the handle, just assume it is ok.
+ if (!(IsHandleSynchronous(handle, access) ?? true))
+ throw new ArgumentException(SR.Arg_HandleNotSync, nameof(handle));
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs
index 291a30bb5..ddbac1bf7 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs
@@ -52,17 +52,29 @@ namespace System.IO
private PreAllocatedOverlapped _preallocatedOverlapped; // optimization for async ops to avoid per-op allocations
private FileStreamCompletionSource _currentOverlappedOwner; // async op currently using the preallocated overlapped
- private void Init(FileMode mode, FileShare share)
+ private void Init(FileMode mode, FileShare share, string originalPath)
{
- // Disallow access to all non-file devices from the Win32FileStream
- // constructors that take a String. Everyone else can call
- // CreateFile themselves then use the constructor that takes an
- // IntPtr. Disallows "con:", "com1:", "lpt1:", etc.
- int fileType = Interop.Kernel32.GetFileType(_fileHandle);
- if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
+ if (!PathInternal.IsExtended(originalPath))
{
- _fileHandle.Dispose();
- throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles);
+ // To help avoid stumbling into opening COM/LPT ports by accident, we will block on non file handles unless
+ // we were explicitly passed a path that has \\?\. GetFullPath() will turn paths like C:\foo\con.txt into
+ // \\.\CON, so we'll only allow the \\?\ syntax.
+
+ int fileType = Interop.Kernel32.GetFileType(_fileHandle);
+ if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
+ {
+ int errorCode = fileType == Interop.Kernel32.FileTypes.FILE_TYPE_UNKNOWN
+ ? Marshal.GetLastWin32Error()
+ : Interop.Errors.ERROR_SUCCESS;
+
+ _fileHandle.Dispose();
+
+ if (errorCode != Interop.Errors.ERROR_SUCCESS)
+ {
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ }
+ throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles);
+ }
}
// This is necessary for async IO using IO Completion ports via our
@@ -161,8 +173,7 @@ namespace System.IO
}
else if (!useAsyncIO)
{
- if (handleType != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE)
- VerifyHandleIsSync(handle, access);
+ VerifyHandleIsSync(handle, handleType, access);
}
if (_canSeek)
@@ -171,75 +182,31 @@ namespace System.IO
_filePosition = 0;
}
- private unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
+ private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default;
if ((share & FileShare.Inheritable) != 0)
{
- secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES();
- secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
-
- secAttrs.bInheritHandle = Interop.BOOL.TRUE;
- }
- return secAttrs;
- }
-
- // Verifies that this handle supports synchronous IO operations (unless you
- // didn't open it for either reading or writing).
- private unsafe static void VerifyHandleIsSync(SafeFileHandle handle, FileAccess access)
- {
- // Do NOT use this method on pipes. Reading or writing to a pipe may
- // cause an app to block incorrectly, introducing a deadlock (depending
- // on whether a write will wake up an already-blocked thread or this
- // Win32FileStream's thread).
- Debug.Assert(Interop.Kernel32.GetFileType(handle) != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE);
-
- byte* bytes = stackalloc byte[1];
- int numBytesReadWritten;
- int r = -1;
-
- // If the handle is a pipe, ReadFile will block until there
- // has been a write on the other end. We'll just have to deal with it,
- // For the read end of a pipe, you can mess up and
- // accidentally read synchronously from an async pipe.
- if ((access & FileAccess.Read) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor
- {
- r = Interop.Kernel32.ReadFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
- }
- else if ((access & FileAccess.Write) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor
- {
- r = Interop.Kernel32.WriteFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
- }
-
- if (r == 0)
- {
- int errorCode = Marshal.GetLastWin32Error();
- switch (errorCode)
+ secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
{
- case Interop.Errors.ERROR_INVALID_PARAMETER:
- throw new ArgumentException(SR.Arg_HandleNotSync, "handle");
- case Interop.Errors.ERROR_INVALID_HANDLE:
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
- }
+ nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
+ bInheritHandle = Interop.BOOL.TRUE
+ };
}
+ return secAttrs;
}
private bool HasActiveBufferOperation
- {
- get { return _activeBufferOperation != null && !_activeBufferOperation.IsCompleted; }
- }
+ => _activeBufferOperation != null && !_activeBufferOperation.IsCompleted;
- public override bool CanSeek
- {
- get { return _canSeek; }
- }
+ public override bool CanSeek => _canSeek;
private unsafe long GetLengthInternal()
{
Interop.Kernel32.FILE_STANDARD_INFO info = new Interop.Kernel32.FILE_STANDARD_INFO();
if (!Interop.Kernel32.GetFileInformationByHandleEx(_fileHandle, Interop.Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileStandardInfo, out info, (uint)sizeof(Interop.Kernel32.FILE_STANDARD_INFO)))
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
long len = info.EndOfFile;
// If we're writing near the end of the file, we must include our
// internal buffer in our Length calculation. Don't flush because
@@ -307,7 +274,7 @@ namespace System.IO
{
if (!Interop.Kernel32.FlushFileBuffers(_fileHandle))
{
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
@@ -404,7 +371,7 @@ namespace System.IO
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == Interop.Errors.ERROR_INVALID_PARAMETER)
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_FileLengthTooBig);
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
// Return file pointer to where it was before setting length
if (origPos != value)
@@ -506,8 +473,7 @@ namespace System.IO
// Make sure we are reading from the right spot
VerifyOSHandlePosition();
- int errorCode = 0;
- int r = ReadFileNative(_fileHandle, buffer, null, out errorCode);
+ int r = ReadFileNative(_fileHandle, buffer, null, out int errorCode);
if (r == -1)
{
@@ -521,7 +487,7 @@ namespace System.IO
if (errorCode == ERROR_INVALID_PARAMETER)
throw new ArgumentException(SR.Arg_HandleNotSync, "_fileHandle");
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
Debug.Assert(r >= 0, "FileStream's ReadNative is likely broken.");
@@ -621,17 +587,15 @@ namespace System.IO
Debug.Assert(!fileHandle.IsClosed && _canSeek, "!fileHandle.IsClosed && _canSeek");
Debug.Assert(origin >= SeekOrigin.Begin && origin <= SeekOrigin.End, "origin >= SeekOrigin.Begin && origin <= SeekOrigin.End");
- long ret = 0;
-
- if (!Interop.Kernel32.SetFilePointerEx(fileHandle, offset, out ret, (uint)origin))
+ if (!Interop.Kernel32.SetFilePointerEx(fileHandle, offset, out long ret, (uint)origin))
{
if (closeInvalidHandle)
{
- throw Win32Marshal.GetExceptionForWin32Error(GetLastWin32ErrorAndDisposeHandleIfInvalid(throwIfInvalidHandle: false));
+ throw Win32Marshal.GetExceptionForWin32Error(GetLastWin32ErrorAndDisposeHandleIfInvalid(), _path);
}
else
{
- throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
@@ -739,7 +703,7 @@ namespace System.IO
// to a handle opened asynchronously.
if (errorCode == ERROR_INVALID_PARAMETER)
throw new IOException(SR.IO_FileTooLongOrHandleNotSync);
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
Debug.Assert(r >= 0, "FileStream's WriteCore is likely broken.");
@@ -850,7 +814,7 @@ namespace System.IO
}
}
- unsafe private Task<int> ReadNativeAsync(Memory<byte> destination, int numBufferedBytesRead, CancellationToken cancellationToken)
+ private unsafe Task<int> ReadNativeAsync(Memory<byte> destination, int numBufferedBytesRead, CancellationToken cancellationToken)
{
AssertCanRead();
Debug.Assert(_useAsyncIO, "ReadNativeAsync doesn't work on synchronous file streams!");
@@ -875,7 +839,7 @@ namespace System.IO
}
else
{
- destination = default(Memory<byte>);
+ destination = default;
}
}
@@ -938,7 +902,7 @@ namespace System.IO
}
else
{
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING
@@ -1141,7 +1105,7 @@ namespace System.IO
}
else
{
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING
@@ -1238,7 +1202,7 @@ namespace System.IO
}
}
- private int GetLastWin32ErrorAndDisposeHandleIfInvalid(bool throwIfInvalidHandle = false)
+ private int GetLastWin32ErrorAndDisposeHandleIfInvalid()
{
int errorCode = Marshal.GetLastWin32Error();
@@ -1262,9 +1226,6 @@ namespace System.IO
if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
{
_fileHandle.Dispose();
-
- if (throwIfInvalidHandle)
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
return errorCode;
@@ -1418,7 +1379,7 @@ namespace System.IO
break;
default:
// Everything else is an error (and there won't be a callback).
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
@@ -1436,7 +1397,7 @@ namespace System.IO
case Interop.Errors.ERROR_OPERATION_ABORTED: // canceled
throw new OperationCanceledException(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true));
default: // error
- throw Win32Marshal.GetExceptionForWin32Error((int)readAwaitable._errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error((int)readAwaitable._errorCode, _path);
}
// Successful operation. If we got zero bytes, we're done: exit the read/write loop.
@@ -1535,7 +1496,7 @@ namespace System.IO
}
/// <summary>Overlapped callback: store the results, then invoke the continuation delegate.</summary>
- internal unsafe static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
+ internal static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
{
var awaitable = (AsyncCopyToAwaitable)ThreadPoolBoundHandle.GetNativeOverlappedState(pOVERLAP);
@@ -1623,7 +1584,7 @@ namespace System.IO
if (!Interop.Kernel32.LockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh))
{
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
@@ -1636,9 +1597,10 @@ namespace System.IO
if (!Interop.Kernel32.UnlockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh))
{
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
+
private SafeFileHandle ValidateFileHandle(SafeFileHandle fileHandle)
{
if (fileHandle.IsInvalid)
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.cs
index 717b73ff1..fadbef880 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.cs
@@ -6,7 +6,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
-using System.Security;
namespace System.IO
{
@@ -233,7 +232,7 @@ namespace System.IO
try
{
- Init(mode, share);
+ Init(mode, share, path);
}
catch
{
@@ -245,12 +244,6 @@ namespace System.IO
}
}
- private static bool GetDefaultIsAsync(SafeFileHandle handle)
- {
- // This will eventually get more complicated as we can actually check the underlying handle type on Windows
- return handle.IsAsync.HasValue ? handle.IsAsync.Value : false;
- }
-
[Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public virtual IntPtr Handle { get { return SafeFileHandle.DangerousGetHandle(); } }
@@ -304,7 +297,7 @@ namespace System.IO
ReadSpan(new Span<byte>(array, offset, count));
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
if (GetType() == typeof(FileStream) && !_useAsyncIO)
{
@@ -312,7 +305,7 @@ namespace System.IO
{
throw Error.GetFileNotOpen();
}
- return ReadSpan(destination);
+ return ReadSpan(buffer);
}
else
{
@@ -322,7 +315,7 @@ namespace System.IO
// of Read(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
// synchronous ReadSpan, so we similarly call the base Read, which will turn delegate to
// Read(byte[],int,int), which will do the right thing if we're in async mode.
- return base.Read(destination);
+ return base.Read(buffer);
}
}
@@ -355,14 +348,14 @@ namespace System.IO
return ReadAsyncTask(buffer, offset, count, cancellationToken);
}
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (!_useAsyncIO || GetType() != typeof(FileStream))
{
// If we're not using async I/O, delegate to the base, which will queue a call to Read.
// Or if this isn't a concrete FileStream, a derived type may have overridden ReadAsync(byte[],...),
// which was introduced first, so delegate to the base which will delegate to that.
- return base.ReadAsync(destination, cancellationToken);
+ return base.ReadAsync(buffer, cancellationToken);
}
if (cancellationToken.IsCancellationRequested)
@@ -375,7 +368,7 @@ namespace System.IO
throw Error.GetFileNotOpen();
}
- Task<int> t = ReadAsyncInternal(destination, cancellationToken, out int synchronousResult);
+ Task<int> t = ReadAsyncInternal(buffer, cancellationToken, out int synchronousResult);
return t != null ?
new ValueTask<int>(t) :
new ValueTask<int>(synchronousResult);
@@ -412,7 +405,7 @@ namespace System.IO
}
}
- public override void Write(ReadOnlySpan<byte> destination)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
if (GetType() == typeof(FileStream) && !_useAsyncIO)
{
@@ -420,7 +413,7 @@ namespace System.IO
{
throw Error.GetFileNotOpen();
}
- WriteSpan(destination);
+ WriteSpan(buffer);
}
else
{
@@ -430,7 +423,7 @@ namespace System.IO
// of Write(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
// synchronous WriteSpan, so we similarly call the base Write, which will turn delegate to
// Write(byte[],int,int), which will do the right thing if we're in async mode.
- base.Write(destination);
+ base.Write(buffer);
}
}
@@ -461,14 +454,14 @@ namespace System.IO
return WriteAsyncInternal(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken).AsTask();
}
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (!_useAsyncIO || GetType() != typeof(FileStream))
{
// If we're not using async I/O, delegate to the base, which will queue a call to Write.
// Or if this isn't a concrete FileStream, a derived type may have overridden WriteAsync(byte[],...),
// which was introduced first, so delegate to the base which will delegate to that.
- return base.WriteAsync(source, cancellationToken);
+ return base.WriteAsync(buffer, cancellationToken);
}
if (cancellationToken.IsCancellationRequested)
@@ -481,7 +474,7 @@ namespace System.IO
throw Error.GetFileNotOpen();
}
- return WriteAsyncInternal(source, cancellationToken);
+ return WriteAsyncInternal(buffer, cancellationToken);
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs
index 82274b131..62ace0918 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs
@@ -246,7 +246,7 @@ namespace System.IO
internal MemoryFileStreamCompletionSource(FileStream stream, int numBufferedBytes, ReadOnlyMemory<byte> memory) :
base(stream, numBufferedBytes, bytes: null) // this type handles the pinning, so null is passed for bytes
{
- _handle = memory.Retain(pin: true);
+ _handle = memory.Pin();
}
internal override void ReleaseNativeResource()
diff --git a/src/System.Private.CoreLib/shared/System/IO/IOException.cs b/src/System.Private.CoreLib/shared/System/IO/IOException.cs
index 89b25d514..04e653206 100644
--- a/src/System.Private.CoreLib/shared/System/IO/IOException.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/IOException.cs
@@ -17,19 +17,19 @@ namespace System.IO
HResult = HResults.COR_E_IO;
}
- public IOException(String message)
+ public IOException(string message)
: base(message)
{
HResult = HResults.COR_E_IO;
}
- public IOException(String message, int hresult)
+ public IOException(string message, int hresult)
: base(message)
{
HResult = hresult;
}
- public IOException(String message, Exception innerException)
+ public IOException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_IO;
diff --git a/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs
index ffe7f6093..9bac0d818 100644
--- a/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs
@@ -208,7 +208,7 @@ namespace System.IO
{
if (!_exposable)
{
- buffer = default(ArraySegment<byte>);
+ buffer = default;
return false;
}
@@ -367,19 +367,19 @@ namespace System.IO
return n;
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
if (GetType() != typeof(MemoryStream))
{
// MemoryStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
// to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
// should use the behavior of Read(byte[],int,int) overload.
- return base.Read(destination);
+ return base.Read(buffer);
}
EnsureNotClosed();
- int n = Math.Min(_length - _position, destination.Length);
+ int n = Math.Min(_length - _position, buffer.Length);
if (n <= 0)
return 0;
@@ -387,13 +387,13 @@ namespace System.IO
// Read(byte[], int, int) has an n <= 8 optimization, presumably based
// on benchmarking. Determine if/where such a cut-off is here and add
// an equivalent optimization if necessary.
- new Span<byte>(_buffer, _position, n).CopyTo(destination);
+ new Span<byte>(_buffer, _position, n).CopyTo(buffer);
_position += n;
return n;
}
- public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -426,7 +426,7 @@ namespace System.IO
}
}
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -448,9 +448,9 @@ namespace System.IO
// something other than an array and this is a MemoryStream-derived type that doesn't override Read(Span<byte>) will
// it then fall back to doing the ArrayPool/copy behavior.
return new ValueTask<int>(
- MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> destinationArray) ?
+ MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> destinationArray) ?
Read(destinationArray.Array, destinationArray.Offset, destinationArray.Count) :
- Read(destination.Span));
+ Read(buffer.Span));
}
catch (OperationCanceledException oce)
{
@@ -681,14 +681,14 @@ namespace System.IO
_position = i;
}
- public override void Write(ReadOnlySpan<byte> source)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
if (GetType() != typeof(MemoryStream))
{
// MemoryStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
// to this Write(Span<byte>) overload being introduced. In that case, this Write(Span<byte>) overload
// should use the behavior of Write(byte[],int,int) overload.
- base.Write(source);
+ base.Write(buffer);
return;
}
@@ -696,7 +696,7 @@ namespace System.IO
EnsureWriteable();
// Check for overflow
- int i = _position + source.Length;
+ int i = _position + buffer.Length;
if (i < 0)
throw new IOException(SR.IO_StreamTooLong);
@@ -718,11 +718,11 @@ namespace System.IO
_length = i;
}
- source.CopyTo(new Span<byte>(_buffer, _position, source.Length));
+ buffer.CopyTo(new Span<byte>(_buffer, _position, buffer.Length));
_position = i;
}
- public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -752,7 +752,7 @@ namespace System.IO
}
}
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -763,13 +763,13 @@ namespace System.IO
{
// See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>).
// Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
- if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> sourceArray))
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> sourceArray))
{
Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count);
}
else
{
- Write(source.Span);
+ Write(buffer.Span);
}
return default;
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs
index fd24cc810..ecf71e612 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs
@@ -23,7 +23,7 @@ namespace System.IO
if (path.Length == 0)
throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
- if (path.IndexOf('\0') != -1)
+ if (path.Contains('\0'))
throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
// Expand with current directory if necessary
@@ -34,7 +34,7 @@ namespace System.IO
// We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist,
// and turns it into a full path, which we only want if fullCheck is true.
- string collapsedString = RemoveRelativeSegments(path);
+ string collapsedString = PathInternal.RemoveRelativeSegments(path, PathInternal.GetRootLength(path));
Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path,
"Either we've removed characters, or the string should be unmodified from the input path.");
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs
index b921db9e6..ddfd7966b 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs
@@ -5,7 +5,14 @@
using System.Diagnostics;
using System.Text;
+#if MS_IO_REDIST
+using System;
+using System.IO;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
public static partial class Path
{
@@ -34,16 +41,16 @@ namespace System.IO
throw new ArgumentNullException(nameof(path));
// If the path would normalize to string empty, we'll consider it empty
- if (PathInternal.IsEffectivelyEmpty(path))
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
// Embedded null characters are the only invalid character case we trully care about.
// This is because the nulls will signal the end of the string to Win32 and therefore have
// unpredictable results.
- if (path.IndexOf('\0') != -1)
+ if (path.Contains('\0'))
throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
- if (PathInternal.IsExtended(path))
+ if (PathInternal.IsExtended(path.AsSpan()))
{
// \\?\ paths are considered normalized by definition. Windows doesn't normalize \\?\
// paths and neither should we. Even if we wanted to GetFullPathName does not work
@@ -72,6 +79,9 @@ namespace System.IO
if (IsPathFullyQualified(path))
return GetFullPath(path);
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
+ return basePath;
+
int length = path.Length;
string combinedPath = null;
@@ -80,30 +90,30 @@ namespace System.IO
// Path is current drive rooted i.e. starts with \:
// "\Foo" and "C:\Bar" => "C:\Foo"
// "\Foo" and "\\?\C:\Bar" => "\\?\C:\Foo"
- combinedPath = Join(GetPathRoot(basePath.AsSpan()), path);
+ combinedPath = Join(GetPathRoot(basePath.AsSpan()), path.AsSpan(1)); // Cut the separator to ensure we don't end up with two separators when joining with the root.
}
else if (length >= 2 && PathInternal.IsValidDriveChar(path[0]) && path[1] == PathInternal.VolumeSeparatorChar)
{
// Drive relative paths
Debug.Assert(length == 2 || !PathInternal.IsDirectorySeparator(path[2]));
- if (StringSpanHelpers.Equals(GetVolumeName(path), GetVolumeName(basePath)))
+ if (GetVolumeName(path.AsSpan()).EqualsOrdinal(GetVolumeName(basePath.AsSpan())))
{
// Matching root
// "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
// "C:Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
- combinedPath = Join(basePath, path.AsSpan().Slice(2));
+ combinedPath = Join(basePath.AsSpan(), path.AsSpan(2));
}
else
{
// No matching root, root to specified drive
// "D:Foo" and "C:\Bar" => "D:Foo"
// "D:Foo" and "\\?\C:\Bar" => "\\?\D:\Foo"
- combinedPath = !PathInternal.IsDevice(basePath)
+ combinedPath = !PathInternal.IsDevice(basePath.AsSpan())
? path.Insert(2, @"\")
: length == 2
- ? JoinInternal(basePath.AsSpan().Slice(0, 4), path, @"\")
- : JoinInternal(basePath.AsSpan().Slice(0, 4), path.AsSpan().Slice(0, 2), @"\", path.AsSpan().Slice(2));
+ ? JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(), @"\".AsSpan())
+ : JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(0, 2), @"\".AsSpan(), path.AsSpan(2));
}
}
else
@@ -111,37 +121,70 @@ namespace System.IO
// "Simple" relative path
// "Foo" and "C:\Bar" => "C:\Bar\Foo"
// "Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
- combinedPath = JoinInternal(basePath, path);
+ combinedPath = JoinInternal(basePath.AsSpan(), path.AsSpan());
}
- // Device paths are normalized by definition, so passing something of this format
- // to GetFullPath() won't do anything by design. Additionally, GetFullPathName() in
- // Windows doesn't root them properly. As such we need to manually remove segments.
- return PathInternal.IsDevice(combinedPath)
- ? RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath))
+ // Device paths are normalized by definition, so passing something of this format (i.e. \\?\C:\.\tmp, \\.\C:\foo)
+ // to Windows APIs won't do anything by design. Additionally, GetFullPathName() in Windows doesn't root
+ // them properly. As such we need to manually remove segments and not use GetFullPath().
+
+ return PathInternal.IsDevice(combinedPath.AsSpan())
+ ? PathInternal.RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath.AsSpan()))
: GetFullPath(combinedPath);
}
public static string GetTempPath()
{
- StringBuilder sb = StringBuilderCache.Acquire(Interop.Kernel32.MAX_PATH);
- uint r = Interop.Kernel32.GetTempPathW(Interop.Kernel32.MAX_PATH, sb);
- if (r == 0)
+ Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
+ var builder = new ValueStringBuilder(initialBuffer);
+
+ GetTempPath(ref builder);
+
+ string path = PathHelper.Normalize(ref builder);
+ builder.Dispose();
+ return path;
+ }
+
+ private static void GetTempPath(ref ValueStringBuilder builder)
+ {
+ uint result = 0;
+ while ((result = Interop.Kernel32.GetTempPathW(builder.Capacity, ref builder.GetPinnableReference())) > builder.Capacity)
+ {
+ // Reported size is greater than the buffer size. Increase the capacity.
+ builder.EnsureCapacity(checked((int)result));
+ }
+
+ if (result == 0)
throw Win32Marshal.GetExceptionForLastWin32Error();
- return GetFullPath(StringBuilderCache.GetStringAndRelease(sb));
+
+ builder.Length = (int)result;
}
// Returns a unique temporary file name, and creates a 0-byte file by that
// name on disk.
public static string GetTempFileName()
{
- string path = GetTempPath();
+ Span<char> initialTempPathBuffer = stackalloc char[PathInternal.MaxShortPath];
+ ValueStringBuilder tempPathBuilder = new ValueStringBuilder(initialTempPathBuffer);
+
+ GetTempPath(ref tempPathBuilder);
+
+ Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
+ var builder = new ValueStringBuilder(initialBuffer);
- StringBuilder sb = StringBuilderCache.Acquire(Interop.Kernel32.MAX_PATH);
- uint r = Interop.Kernel32.GetTempFileNameW(path, "tmp", 0, sb);
- if (r == 0)
+ uint result = Interop.Kernel32.GetTempFileNameW(
+ ref tempPathBuilder.GetPinnableReference(), "tmp", 0, ref builder.GetPinnableReference());
+
+ tempPathBuilder.Dispose();
+
+ if (result == 0)
throw Win32Marshal.GetExceptionForLastWin32Error();
- return StringBuilderCache.GetStringAndRelease(sb);
+
+ builder.Length = builder.RawChars.IndexOf('\0');
+
+ string path = PathHelper.Normalize(ref builder);
+ builder.Dispose();
+ return path;
}
// Tests if the given path contains a root. A path is considered rooted
@@ -169,14 +212,14 @@ namespace System.IO
// only contains whitespace characters an ArgumentException gets thrown.
public static string GetPathRoot(string path)
{
- if (PathInternal.IsEffectivelyEmpty(path))
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
return null;
ReadOnlySpan<char> result = GetPathRoot(path.AsSpan());
if (path.Length == result.Length)
return PathInternal.NormalizeDirectorySeparators(path);
- return PathInternal.NormalizeDirectorySeparators(new string(result));
+ return PathInternal.NormalizeDirectorySeparators(result.ToString());
}
/// <remarks>
@@ -237,11 +280,11 @@ namespace System.IO
{
bool isDevice = PathInternal.IsDevice(path);
- if (!isDevice && StringSpanHelpers.Equals(path.Slice(0, 2), @"\\") )
+ if (!isDevice && path.Slice(0, 2).EqualsOrdinal(@"\\".AsSpan()) )
return 2;
else if (isDevice && path.Length >= 8
- && (StringSpanHelpers.Equals(path.Slice(0, 8), PathInternal.UncExtendedPathPrefix)
- || StringSpanHelpers.Equals(path.Slice(5, 4), @"UNC\")))
+ && (path.Slice(0, 8).EqualsOrdinal(PathInternal.UncExtendedPathPrefix.AsSpan())
+ || path.Slice(5, 4).EqualsOrdinal(@"UNC\".AsSpan())))
return 8;
return -1;
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.cs b/src/System.Private.CoreLib/shared/System/IO/Path.cs
index 41ae1cd0b..7b4565a13 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.cs
@@ -6,7 +6,14 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
+#if MS_IO_REDIST
+using System;
+using System.IO;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
// Provides methods for processing file system strings in a cross-platform manner.
// Most of the methods don't do a complete parsing (such as examining a UNC hostname),
@@ -79,10 +86,10 @@ namespace System.IO
/// </remarks>
public static string GetDirectoryName(string path)
{
- if (path == null || PathInternal.IsEffectivelyEmpty(path))
+ if (path == null || PathInternal.IsEffectivelyEmpty(path.AsSpan()))
return null;
- int end = GetDirectoryNameOffset(path);
+ int end = GetDirectoryNameOffset(path.AsSpan());
return end >= 0 ? PathInternal.NormalizeDirectorySeparators(path.Substring(0, end)) : null;
}
@@ -130,7 +137,7 @@ namespace System.IO
if (path == null)
return null;
- return new string(GetExtension(path.AsSpan()));
+ return GetExtension(path.AsSpan()).ToString();
}
/// <summary>
@@ -173,7 +180,7 @@ namespace System.IO
if (path.Length == result.Length)
return path;
- return new string(result);
+ return result.ToString();
}
/// <summary>
@@ -204,7 +211,7 @@ namespace System.IO
if (path.Length == result.Length)
return path;
- return new string(result);
+ return result.ToString();
}
/// <summary>
@@ -388,9 +395,9 @@ namespace System.IO
public static string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2)
{
if (path1.Length == 0)
- return new string(path2);
+ return path2.ToString();
if (path2.Length == 0)
- return new string(path1);
+ return path1.ToString();
return JoinInternal(path1, path2);
}
@@ -409,6 +416,16 @@ namespace System.IO
return JoinInternal(path1, path2, path3);
}
+ public static string Join(string path1, string path2)
+ {
+ return Join(path1.AsSpan(), path2.AsSpan());
+ }
+
+ public static string Join(string path1, string path2, string path3)
+ {
+ return Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan());
+ }
+
public static bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, Span<char> destination, out int charsWritten)
{
charsWritten = 0;
@@ -477,22 +494,6 @@ namespace System.IO
return true;
}
- private static string CombineInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
- {
- if (first.Length == 0)
- return second.Length == 0
- ? string.Empty
- : new string(second);
-
- if (second.Length == 0)
- return new string(first);
-
- if (IsPathRooted(second))
- return new string(second);
-
- return JoinInternal(first, second);
- }
-
private static string CombineInternal(string first, string second)
{
if (string.IsNullOrEmpty(first))
@@ -504,7 +505,7 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return second;
- return JoinInternal(first, second);
+ return JoinInternal(first.AsSpan(), second.AsSpan());
}
private static string CombineInternal(string first, string second, string third)
@@ -521,7 +522,7 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return CombineInternal(second, third);
- return JoinInternal(first, second, third);
+ return JoinInternal(first.AsSpan(), second.AsSpan(), third.AsSpan());
}
private static string CombineInternal(string first, string second, string third, string fourth)
@@ -542,10 +543,10 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return CombineInternal(second, third, fourth);
- return JoinInternal(first, second, third, fourth);
+ return JoinInternal(first.AsSpan(), second.AsSpan(), third.AsSpan(), fourth.AsSpan());
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
{
Debug.Assert(first.Length > 0 && second.Length > 0, "should have dealt with empty paths");
@@ -554,7 +555,11 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second))
{
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + (hasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length, HasSeparator: hasSeparator),
(destination, state) =>
@@ -567,7 +572,7 @@ namespace System.IO
}
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third)
{
Debug.Assert(first.Length > 0 && second.Length > 0 && third.Length > 0, "should have dealt with empty paths");
@@ -578,7 +583,11 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second), t = &MemoryMarshal.GetReference(third))
{
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + third.Length + (firstHasSeparator ? 0 : 1) + (thirdHasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length,
Third: (IntPtr)t, ThirdLength: third.Length, FirstHasSeparator: firstHasSeparator, ThirdHasSeparator: thirdHasSeparator),
@@ -595,7 +604,7 @@ namespace System.IO
}
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third, ReadOnlySpan<char> fourth)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third, ReadOnlySpan<char> fourth)
{
Debug.Assert(first.Length > 0 && second.Length > 0 && third.Length > 0 && fourth.Length > 0, "should have dealt with empty paths");
@@ -608,7 +617,12 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second), t = &MemoryMarshal.GetReference(third), u = &MemoryMarshal.GetReference(fourth))
{
+
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + third.Length + fourth.Length + (firstHasSeparator ? 0 : 1) + (thirdHasSeparator ? 0 : 1) + (fourthHasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length,
Third: (IntPtr)t, ThirdLength: third.Length, Fourth: (IntPtr)u, FourthLength:fourth.Length,
@@ -688,93 +702,6 @@ namespace System.IO
}
/// <summary>
- /// Try to remove relative segments from the given path (without combining with a root).
- /// </summary>
- /// <param name="skip">Skip the specified number of characters before evaluating.</param>
- private static string RemoveRelativeSegments(string path, int skip = 0)
- {
- bool flippedSeparator = false;
-
- // Remove "//", "/./", and "/../" from the path by copying each character to the output,
- // except the ones we're removing, such that the builder contains the normalized path
- // at the end.
- StringBuilder sb = StringBuilderCache.Acquire(path.Length);
- if (skip > 0)
- {
- sb.Append(path, 0, skip);
- }
-
- for (int i = skip; i < path.Length; i++)
- {
- char c = path[i];
-
- if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
- {
- // Skip this character if it's a directory separator and if the next character is, too,
- // e.g. "parent//child" => "parent/child"
- if (PathInternal.IsDirectorySeparator(path[i + 1]))
- {
- continue;
- }
-
- // Skip this character and the next if it's referring to the current directory,
- // e.g. "parent/./child" => "parent/child"
- if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
- path[i + 1] == '.')
- {
- i++;
- continue;
- }
-
- // Skip this character and the next two if it's referring to the parent directory,
- // e.g. "parent/child/../grandchild" => "parent/grandchild"
- if (i + 2 < path.Length &&
- (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
- path[i + 1] == '.' && path[i + 2] == '.')
- {
- // Unwind back to the last slash (and if there isn't one, clear out everything).
- int s;
- for (s = sb.Length - 1; s >= 0; s--)
- {
- if (PathInternal.IsDirectorySeparator(sb[s]))
- {
- sb.Length = s;
- break;
- }
- }
- if (s < 0)
- {
- sb.Length = 0;
- }
-
- i += 2;
- continue;
- }
- }
-
- // Normalize the directory separator if needed
- if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar)
- {
- c = PathInternal.DirectorySeparatorChar;
- flippedSeparator = true;
- }
-
- sb.Append(c);
- }
-
- if (flippedSeparator || sb.Length != path.Length)
- {
- return StringBuilderCache.GetStringAndRelease(sb);
- }
- else
- {
- // We haven't changed the source path, return the original
- StringBuilderCache.Release(sb);
- return path;
- }
- }
-
- /// <summary>
/// Create a relative path from one path to another. Paths will be resolved before calculating the difference.
/// Default path comparison for the active platform will be used (OrdinalIgnoreCase for Windows or Mac, Ordinal for Unix).
/// </summary>
@@ -790,7 +717,7 @@ namespace System.IO
private static string GetRelativePath(string relativeTo, string path, StringComparison comparisonType)
{
if (string.IsNullOrEmpty(relativeTo)) throw new ArgumentNullException(nameof(relativeTo));
- if (PathInternal.IsEffectivelyEmpty(path)) throw new ArgumentNullException(nameof(path));
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan())) throw new ArgumentNullException(nameof(path));
Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
relativeTo = GetFullPath(relativeTo);
@@ -808,10 +735,10 @@ namespace System.IO
// Trailing separators aren't significant for comparison
int relativeToLength = relativeTo.Length;
- if (PathInternal.EndsInDirectorySeparator(relativeTo))
+ if (PathInternal.EndsInDirectorySeparator(relativeTo.AsSpan()))
relativeToLength--;
- bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path);
+ bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path.AsSpan());
int pathLength = path.Length;
if (pathEndsInSeparator)
pathLength--;
@@ -834,13 +761,14 @@ namespace System.IO
// Add parent segments for segments past the common on the "from" path
if (commonLength < relativeToLength)
{
- sb.Append(PathInternal.ParentDirectoryPrefix);
+ sb.Append("..");
- for (int i = commonLength; i < relativeToLength; i++)
+ for (int i = commonLength + 1; i < relativeToLength; i++)
{
if (PathInternal.IsDirectorySeparator(relativeTo[i]))
{
- sb.Append(PathInternal.ParentDirectoryPrefix);
+ sb.Append(DirectorySeparatorChar);
+ sb.Append("..");
}
}
}
@@ -852,11 +780,20 @@ namespace System.IO
}
// Now add the rest of the "to" path, adding back the trailing separator
- int count = pathLength - commonLength;
+ int differenceLength = pathLength - commonLength;
if (pathEndsInSeparator)
- count++;
+ differenceLength++;
+
+ if (differenceLength > 0)
+ {
+ if (sb.Length > 0)
+ {
+ sb.Append(DirectorySeparatorChar);
+ }
+
+ sb.Append(path, commonLength, differenceLength);
+ }
- sb.Append(path, commonLength, count);
return StringBuilderCache.GetStringAndRelease(sb);
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs
index 74ceed10a..bada2f5cd 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs
@@ -26,30 +26,57 @@ namespace System.IO
internal static string Normalize(string path)
{
Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
- ValueStringBuilder builder = new ValueStringBuilder(initialBuffer);
+ var builder = new ValueStringBuilder(initialBuffer);
// Get the full path
- GetFullPathName(path, ref builder);
+ GetFullPathName(path.AsSpan(), ref builder);
// If we have the exact same string we were passed in, don't allocate another string.
// TryExpandShortName does this input identity check.
- string result = builder.AsSpan().Contains('~')
+ string result = builder.AsSpan().IndexOf('~') >= 0
? TryExpandShortFileName(ref builder, originalPath: path)
- : builder.AsSpan().Equals(path.AsSpan()) ? path : builder.ToString();
+ : builder.AsSpan().Equals(path.AsSpan(), StringComparison.Ordinal) ? path : builder.ToString();
// Clear the buffer
builder.Dispose();
return result;
}
- private static void GetFullPathName(string path, ref ValueStringBuilder builder)
+ /// <summary>
+ /// Normalize the given path.
+ /// </summary>
+ /// <remarks>
+ /// Exceptions are the same as the string overload.
+ /// </remarks>
+ internal static string Normalize(ref ValueStringBuilder path)
+ {
+ Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
+ var builder = new ValueStringBuilder(initialBuffer);
+
+ // Get the full path
+ GetFullPathName(path.AsSpan(terminate: true), ref builder);
+
+ string result = builder.AsSpan().IndexOf('~') >= 0
+ ? TryExpandShortFileName(ref builder, originalPath: null)
+ : builder.ToString();
+
+ // Clear the buffer
+ builder.Dispose();
+ return result;
+ }
+
+ /// <summary>
+ /// Calls GetFullPathName on the given path.
+ /// </summary>
+ /// <param name="path">The path name. MUST be null terminated after the span.</param>
+ private static void GetFullPathName(ReadOnlySpan<char> path, ref ValueStringBuilder builder)
{
// If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as
// it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here.
Debug.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path));
uint result = 0;
- while ((result = Interop.Kernel32.GetFullPathNameW(path, (uint)builder.Capacity, ref builder.GetPinnableReference(), IntPtr.Zero)) > builder.Capacity)
+ while ((result = Interop.Kernel32.GetFullPathNameW(ref MemoryMarshal.GetReference(path), (uint)builder.Capacity, ref builder.GetPinnableReference(), IntPtr.Zero)) > builder.Capacity)
{
// Reported size is greater than the buffer size. Increase the capacity.
builder.EnsureCapacity(checked((int)result));
@@ -61,13 +88,13 @@ namespace System.IO
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == 0)
errorCode = Interop.Errors.ERROR_BAD_PATHNAME;
- throw Win32Marshal.GetExceptionForWin32Error(errorCode, path);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, path.ToString());
}
builder.Length = (int)result;
}
- private static int PrependDevicePathChars(ref ValueStringBuilder content, bool isDosUnc, ref ValueStringBuilder buffer)
+ internal static int PrependDevicePathChars(ref ValueStringBuilder content, bool isDosUnc, ref ValueStringBuilder buffer)
{
int length = content.Length;
@@ -84,7 +111,7 @@ namespace System.IO
buffer.Append(PathInternal.UncExtendedPathPrefix);
// Copy Server\Share\... over to the buffer
- buffer.Append(content.AsSpan().Slice(PathInternal.UncPrefixLength));
+ buffer.Append(content.AsSpan(PathInternal.UncPrefixLength));
// Return the prefix difference
return PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength;
@@ -98,7 +125,7 @@ namespace System.IO
}
}
- private static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
+ internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
{
// We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To
// avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls.
@@ -119,7 +146,7 @@ namespace System.IO
bool isDevice = PathInternal.IsDevice(outputBuilder.AsSpan());
// As this is a corner case we're not going to add a stackalloc here to keep the stack pressure down.
- ValueStringBuilder inputBuilder = new ValueStringBuilder();
+ var inputBuilder = new ValueStringBuilder();
bool isDosUnc = false;
int rootDifference = 0;
@@ -149,12 +176,10 @@ namespace System.IO
bool success = false;
int foundIndex = inputBuilder.Length - 1;
- // Need to null terminate the input builder
- inputBuilder.Append('\0');
-
while (!success)
{
- uint result = Interop.Kernel32.GetLongPathNameW(ref inputBuilder.GetPinnableReference(), ref outputBuilder.GetPinnableReference(), (uint)outputBuilder.Capacity);
+ uint result = Interop.Kernel32.GetLongPathNameW(
+ ref inputBuilder.GetPinnableReference(terminate: true), ref outputBuilder.GetPinnableReference(), (uint)outputBuilder.Capacity);
// Replace any temporary null we added
if (inputBuilder[foundIndex] == '\0') inputBuilder[foundIndex] = '\\';
@@ -198,14 +223,11 @@ namespace System.IO
if (foundIndex < inputLength - 1)
{
// It was a partial find, put the non-existent part of the path back
- outputBuilder.Append(inputBuilder.AsSpan().Slice(foundIndex, inputBuilder.Length - foundIndex));
+ outputBuilder.Append(inputBuilder.AsSpan(foundIndex, inputBuilder.Length - foundIndex));
}
}
}
- // Need to trim out the trailing separator in the input builder
- inputBuilder.Length = inputBuilder.Length - 1;
-
// If we were able to expand the path, use it, otherwise use the original full path result
ref ValueStringBuilder builderToUse = ref (success ? ref outputBuilder : ref inputBuilder);
@@ -218,10 +240,10 @@ namespace System.IO
builderToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\';
// Strip out any added characters at the front of the string
- ReadOnlySpan<char> output = builderToUse.AsSpan().Slice(rootDifference);
+ ReadOnlySpan<char> output = builderToUse.AsSpan(rootDifference);
- string returnValue = output.Equals(originalPath.AsSpan())
- ? originalPath : new string(output);
+ string returnValue = ((originalPath != null) && output.Equals(originalPath.AsSpan(), StringComparison.Ordinal))
+ ? originalPath : output.ToString();
inputBuilder.Dispose();
return returnValue;
diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs
index 81d51ba4b..5f9ee0e02 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs
@@ -70,7 +70,7 @@ namespace System.IO
return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
}
- private static bool EndsWithPeriodOrSpace(string path)
+ internal static bool EndsWithPeriodOrSpace(string path)
{
if (string.IsNullOrEmpty(path))
return false;
@@ -130,7 +130,7 @@ namespace System.IO
// In any case, all internal usages should be hitting normalize path (Path.GetFullPath) before they hit this
// shimming method. (Or making a change that doesn't impact normalization, such as adding a filename to a
// normalized base path.)
- if (IsPartiallyQualified(path) || IsDevice(path))
+ if (IsPartiallyQualified(path.AsSpan()) || IsDevice(path.AsSpan()))
return path;
// Given \\server\share in longpath becomes \\?\UNC\server\share
@@ -270,19 +270,6 @@ namespace System.IO
return i;
}
- private static bool StartsWithOrdinal(ReadOnlySpan<char> source, string value)
- {
- if (source.Length < value.Length)
- return false;
-
- for (int i = 0; i < value.Length; i++)
- {
- if (value[i] != source[i])
- return false;
- }
- return true;
- }
-
/// <summary>
/// Returns true if the path specified is relative to the current drive or working directory.
/// Returns false if the path is fixed to a specific drive or UNC path. This method does no
diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs
index eb06c2608..1b08a2612 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs
@@ -2,6 +2,9 @@
// 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.Diagnostics;
+using System.Text;
+
namespace System.IO
{
/// <summary>Contains internal path helpers that are shared between many projects.</summary>
@@ -19,10 +22,10 @@ namespace System.IO
internal static bool StartsWithDirectorySeparator(ReadOnlySpan<char> path) => path.Length > 0 && IsDirectorySeparator(path[0]);
internal static string EnsureTrailingSeparator(string path)
- => EndsInDirectorySeparator(path) ? path : path + DirectorySeparatorCharAsString;
+ => EndsInDirectorySeparator(path.AsSpan()) ? path : path + DirectorySeparatorCharAsString;
internal static string TrimEndingDirectorySeparator(string path) =>
- EndsInDirectorySeparator(path) && !IsRoot(path) ?
+ EndsInDirectorySeparator(path.AsSpan()) && !IsRoot(path.AsSpan()) ?
path.Substring(0, path.Length - 1) :
path;
@@ -63,7 +66,7 @@ namespace System.IO
/// <summary>
/// Gets the count of common characters from the left optionally ignoring case
/// </summary>
- unsafe internal static int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
+ internal static unsafe int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
{
if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0;
@@ -94,8 +97,8 @@ namespace System.IO
/// </summary>
internal static bool AreRootsEqual(string first, string second, StringComparison comparisonType)
{
- int firstRootLength = GetRootLength(first);
- int secondRootLength = GetRootLength(second);
+ int firstRootLength = GetRootLength(first.AsSpan());
+ int secondRootLength = GetRootLength(second.AsSpan());
return firstRootLength == secondRootLength
&& string.Compare(
@@ -106,5 +109,121 @@ namespace System.IO
length: firstRootLength,
comparisonType: comparisonType) == 0;
}
+
+ /// <summary>
+ /// Try to remove relative segments from the given path (without combining with a root).
+ /// </summary>
+ /// <param name="rootLength">The length of the root of the given path</param>
+ internal static string RemoveRelativeSegments(string path, int rootLength)
+ {
+ Span<char> initialBuffer = stackalloc char[260 /* PathInternal.MaxShortPath */];
+ ValueStringBuilder sb = new ValueStringBuilder(initialBuffer);
+
+ if (RemoveRelativeSegments(path.AsSpan(), rootLength, ref sb))
+ {
+ path = sb.ToString();
+ }
+
+ sb.Dispose();
+ return path;
+ }
+
+ /// <summary>
+ /// Try to remove relative segments from the given path (without combining with a root).
+ /// </summary>
+ /// <param name="rootLength">The length of the root of the given path</param>
+ /// <returns>"true" if the path was modified</returns>
+ internal static bool RemoveRelativeSegments(ReadOnlySpan<char> path, int rootLength, ref ValueStringBuilder sb)
+ {
+ Debug.Assert(rootLength > 0);
+ bool flippedSeparator = false;
+
+ int skip = rootLength;
+ // We treat "\.." , "\." and "\\" as a relative segment. We want to collapse the first separator past the root presuming
+ // the root actually ends in a separator. Otherwise the first segment for RemoveRelativeSegments
+ // in cases like "\\?\C:\.\" and "\\?\C:\..\", the first segment after the root will be ".\" and "..\" which is not considered as a relative segment and hence not be removed.
+ if (PathInternal.IsDirectorySeparator(path[skip - 1]))
+ skip--;
+
+ // Remove "//", "/./", and "/../" from the path by copying each character to the output,
+ // except the ones we're removing, such that the builder contains the normalized path
+ // at the end.
+ if (skip > 0)
+ {
+ sb.Append(path.Slice(0, skip));
+ }
+
+ for (int i = skip; i < path.Length; i++)
+ {
+ char c = path[i];
+
+ if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
+ {
+ // Skip this character if it's a directory separator and if the next character is, too,
+ // e.g. "parent//child" => "parent/child"
+ if (PathInternal.IsDirectorySeparator(path[i + 1]))
+ {
+ continue;
+ }
+
+ // Skip this character and the next if it's referring to the current directory,
+ // e.g. "parent/./child" => "parent/child"
+ if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
+ path[i + 1] == '.')
+ {
+ i++;
+ continue;
+ }
+
+ // Skip this character and the next two if it's referring to the parent directory,
+ // e.g. "parent/child/../grandchild" => "parent/grandchild"
+ if (i + 2 < path.Length &&
+ (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
+ path[i + 1] == '.' && path[i + 2] == '.')
+ {
+ // Unwind back to the last slash (and if there isn't one, clear out everything).
+ int s;
+ for (s = sb.Length - 1; s >= skip; s--)
+ {
+ if (PathInternal.IsDirectorySeparator(sb[s]))
+ {
+ sb.Length = (i + 3 >= path.Length && s == skip) ? s + 1 : s; // to avoid removing the complete "\tmp\" segment in cases like \\?\C:\tmp\..\, C:\tmp\..
+ break;
+ }
+ }
+ if (s < skip)
+ {
+ sb.Length = skip;
+ }
+
+ i += 2;
+ continue;
+ }
+ }
+
+ // Normalize the directory separator if needed
+ if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar)
+ {
+ c = PathInternal.DirectorySeparatorChar;
+ flippedSeparator = true;
+ }
+
+ sb.Append(c);
+ }
+
+ // If we haven't changed the source path, return the original
+ if (!flippedSeparator && sb.Length == path.Length)
+ {
+ return false;
+ }
+
+ // We may have eaten the trailing separator from the root when we started and not replaced it
+ if (skip != rootLength && sb.Length < rootLength)
+ {
+ sb.Append(path[rootLength - 1]);
+ }
+
+ return true;
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs
index dfcc05d06..94331a2ef 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs
@@ -38,9 +38,9 @@ namespace System.IO
Initialize(ptr, len, len, FileAccess.Read);
}
- public override int Read(Span<byte> destination) => ReadCore(destination);
+ public override int Read(Span<byte> buffer) => ReadCore(buffer);
- public override void Write(ReadOnlySpan<byte> source) => WriteCore(source);
+ public override void Write(ReadOnlySpan<byte> buffer) => WriteCore(buffer);
~PinnedBufferMemoryStream()
{
diff --git a/src/System.Private.CoreLib/shared/System/IO/Stream.cs b/src/System.Private.CoreLib/shared/System/IO/Stream.cs
new file mode 100644
index 000000000..faeb69fb5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/IO/Stream.cs
@@ -0,0 +1,1322 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Abstract base class for all Streams. Provides
+** default implementations of asynchronous reads & writes, in
+** terms of the synchronous reads & writes (and vice versa).
+**
+**
+===========================================================*/
+
+using System.Buffers;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.IO
+{
+ public abstract partial class Stream : MarshalByRefObject, IDisposable
+ {
+ public static readonly Stream Null = new NullStream();
+
+ // We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
+ // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
+ // improvement in Copy performance.
+ private const int DefaultCopyBufferSize = 81920;
+
+ // To implement Async IO operations on streams that don't support async IO
+
+ private ReadWriteTask _activeReadWriteTask;
+ private SemaphoreSlim _asyncActiveSemaphore;
+
+ internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
+ {
+ // Lazily-initialize _asyncActiveSemaphore. As we're never accessing the SemaphoreSlim's
+ // WaitHandle, we don't need to worry about Disposing it.
+ return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
+ }
+
+ public abstract bool CanRead
+ {
+ get;
+ }
+
+ // If CanSeek is false, Position, Seek, Length, and SetLength should throw.
+ public abstract bool CanSeek
+ {
+ get;
+ }
+
+ public virtual bool CanTimeout
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public abstract bool CanWrite
+ {
+ get;
+ }
+
+ public abstract long Length
+ {
+ get;
+ }
+
+ public abstract long Position
+ {
+ get;
+ set;
+ }
+
+ public virtual int ReadTimeout
+ {
+ get
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ set
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ }
+
+ public virtual int WriteTimeout
+ {
+ get
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ set
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ }
+
+ public Task CopyToAsync(Stream destination)
+ {
+ int bufferSize = GetCopyBufferSize();
+
+ return CopyToAsync(destination, bufferSize);
+ }
+
+ public Task CopyToAsync(Stream destination, int bufferSize)
+ {
+ return CopyToAsync(destination, bufferSize, CancellationToken.None);
+ }
+
+ public Task CopyToAsync(Stream destination, CancellationToken cancellationToken)
+ {
+ int bufferSize = GetCopyBufferSize();
+
+ return CopyToAsync(destination, bufferSize, cancellationToken);
+ }
+
+ public virtual Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ return CopyToAsyncInternal(destination, bufferSize, cancellationToken);
+ }
+
+ private async Task CopyToAsyncInternal(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
+ try
+ {
+ while (true)
+ {
+ int bytesRead = await ReadAsync(new Memory<byte>(buffer), cancellationToken).ConfigureAwait(false);
+ if (bytesRead == 0) break;
+ await destination.WriteAsync(new ReadOnlyMemory<byte>(buffer, 0, bytesRead), cancellationToken).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(buffer);
+ }
+ }
+
+ // Reads the bytes from the current stream and writes the bytes to
+ // the destination stream until all bytes are read, starting at
+ // the current position.
+ public void CopyTo(Stream destination)
+ {
+ int bufferSize = GetCopyBufferSize();
+
+ CopyTo(destination, bufferSize);
+ }
+
+ public virtual void CopyTo(Stream destination, int bufferSize)
+ {
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
+ try
+ {
+ int read;
+ while ((read = Read(buffer, 0, buffer.Length)) != 0)
+ {
+ destination.Write(buffer, 0, read);
+ }
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(buffer);
+ }
+ }
+
+ private int GetCopyBufferSize()
+ {
+ int bufferSize = DefaultCopyBufferSize;
+
+ if (CanSeek)
+ {
+ long length = Length;
+ long position = Position;
+ if (length <= position) // Handles negative overflows
+ {
+ // There are no bytes left in the stream to copy.
+ // However, because CopyTo{Async} is virtual, we need to
+ // ensure that any override is still invoked to provide its
+ // own validation, so we use the smallest legal buffer size here.
+ bufferSize = 1;
+ }
+ else
+ {
+ long remaining = length - position;
+ if (remaining > 0)
+ {
+ // In the case of a positive overflow, stick to the default size
+ bufferSize = (int)Math.Min(bufferSize, remaining);
+ }
+ }
+ }
+
+ return bufferSize;
+ }
+
+ // Stream used to require that all cleanup logic went into Close(),
+ // which was thought up before we invented IDisposable. However, we
+ // need to follow the IDisposable pattern so that users can write
+ // sensible subclasses without needing to inspect all their base
+ // classes, and without worrying about version brittleness, from a
+ // base class switching to the Dispose pattern. We're moving
+ // Stream to the Dispose(bool) pattern - that's where all subclasses
+ // should put their cleanup now.
+ public virtual void Close()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ // Note: Never change this to call other virtual methods on Stream
+ // like Write, since the state on subclasses has already been
+ // torn down. This is the last code to run on cleanup for a stream.
+ }
+
+ public abstract void Flush();
+
+ public Task FlushAsync()
+ {
+ return FlushAsync(CancellationToken.None);
+ }
+
+ public virtual Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(state => ((Stream)state).Flush(), this,
+ cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [Obsolete("CreateWaitHandle will be removed eventually. Please use \"new ManualResetEvent(false)\" instead.")]
+ protected virtual WaitHandle CreateWaitHandle()
+ {
+ return new ManualResetEvent(false);
+ }
+
+ public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ return BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true);
+ }
+
+ internal IAsyncResult BeginReadInternal(
+ byte[] buffer, int offset, int count, AsyncCallback callback, object state,
+ bool serializeAsynchronously, bool apm)
+ {
+ if (!CanRead) throw Error.GetReadNotSupported();
+
+ // To avoid a race with a stream's position pointer & generating race conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread if it does a second IO request until the first one completes.
+ var semaphore = EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreTask = null;
+ if (serializeAsynchronously)
+ {
+ semaphoreTask = semaphore.WaitAsync();
+ }
+ else
+ {
+ semaphore.Wait();
+ }
+
+ // Create the task to asynchronously do a Read. This task serves both
+ // as the asynchronous work item and as the IAsyncResult returned to the user.
+ var asyncResult = new ReadWriteTask(true /*isRead*/, apm, delegate
+ {
+ // The ReadWriteTask stores all of the parameters to pass to Read.
+ // As we're currently inside of it, we can get the current task
+ // and grab the parameters from it.
+ var thisTask = Task.InternalCurrent as ReadWriteTask;
+ Debug.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
+
+ try
+ {
+ // Do the Read and return the number of bytes read
+ return thisTask._stream.Read(thisTask._buffer, thisTask._offset, thisTask._count);
+ }
+ finally
+ {
+ // If this implementation is part of Begin/EndXx, then the EndXx method will handle
+ // finishing the async operation. However, if this is part of XxAsync, then there won't
+ // be an end method, and this task is responsible for cleaning up.
+ if (!thisTask._apm)
+ {
+ thisTask._stream.FinishTrackingAsyncOperation();
+ }
+
+ thisTask.ClearBeginState(); // just to help alleviate some memory pressure
+ }
+ }, state, this, buffer, offset, count, callback);
+
+ // Schedule it
+ if (semaphoreTask != null)
+ RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
+ else
+ RunReadWriteTask(asyncResult);
+
+
+ return asyncResult; // return it
+ }
+
+ public virtual int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ var readTask = _activeReadWriteTask;
+
+ if (readTask == null)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple);
+ }
+ else if (readTask != asyncResult)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple);
+ }
+ else if (!readTask._isRead)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple);
+ }
+
+ try
+ {
+ return readTask.GetAwaiter().GetResult(); // block until completion, then get result / propagate any exception
+ }
+ finally
+ {
+ FinishTrackingAsyncOperation();
+ }
+ }
+
+ public Task<int> ReadAsync(byte[] buffer, int offset, int count)
+ {
+ return ReadAsync(buffer, offset, count, CancellationToken.None);
+ }
+
+ public virtual Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ // If cancellation was requested, bail early with an already completed task.
+ // Otherwise, return a task that represents the Begin/End methods.
+ return cancellationToken.IsCancellationRequested
+ ? Task.FromCanceled<int>(cancellationToken)
+ : BeginEndReadAsync(buffer, offset, count);
+ }
+
+ public virtual ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
+ {
+ return new ValueTask<int>(ReadAsync(array.Array, array.Offset, array.Count, cancellationToken));
+ }
+ else
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ return FinishReadAsync(ReadAsync(sharedBuffer, 0, buffer.Length, cancellationToken), sharedBuffer, buffer);
+
+ async ValueTask<int> FinishReadAsync(Task<int> readTask, byte[] localBuffer, Memory<byte> localDestination)
+ {
+ try
+ {
+ int result = await readTask.ConfigureAwait(false);
+ new Span<byte>(localBuffer, 0, result).CopyTo(localDestination.Span);
+ return result;
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(localBuffer);
+ }
+ }
+ }
+ }
+
+ private Task<int> BeginEndReadAsync(byte[] buffer, int offset, int count)
+ {
+ if (!HasOverriddenBeginEndRead())
+ {
+ // If the Stream does not override Begin/EndRead, then we can take an optimized path
+ // that skips an extra layer of tasks / IAsyncResults.
+ return (Task<int>)BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
+ }
+
+ // Otherwise, we need to wrap calls to Begin/EndWrite to ensure we use the derived type's functionality.
+ return TaskFactory<int>.FromAsyncTrim(
+ this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
+ (stream, args, callback, state) => stream.BeginRead(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
+ (stream, asyncResult) => stream.EndRead(asyncResult)); // cached by compiler
+ }
+
+ private struct ReadWriteParameters // struct for arguments to Read and Write calls
+ {
+ internal byte[] Buffer;
+ internal int Offset;
+ internal int Count;
+ }
+
+
+
+ public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ return BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true);
+ }
+
+ internal IAsyncResult BeginWriteInternal(
+ byte[] buffer, int offset, int count, AsyncCallback callback, object state,
+ bool serializeAsynchronously, bool apm)
+ {
+ if (!CanWrite) throw Error.GetWriteNotSupported();
+
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread if it does a second IO request until the first one completes.
+ var semaphore = EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreTask = null;
+ if (serializeAsynchronously)
+ {
+ semaphoreTask = semaphore.WaitAsync(); // kick off the asynchronous wait, but don't block
+ }
+ else
+ {
+ semaphore.Wait(); // synchronously wait here
+ }
+
+ // Create the task to asynchronously do a Write. This task serves both
+ // as the asynchronous work item and as the IAsyncResult returned to the user.
+ var asyncResult = new ReadWriteTask(false /*isRead*/, apm, delegate
+ {
+ // The ReadWriteTask stores all of the parameters to pass to Write.
+ // As we're currently inside of it, we can get the current task
+ // and grab the parameters from it.
+ var thisTask = Task.InternalCurrent as ReadWriteTask;
+ Debug.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
+
+ try
+ {
+ // Do the Write
+ thisTask._stream.Write(thisTask._buffer, thisTask._offset, thisTask._count);
+ return 0; // not used, but signature requires a value be returned
+ }
+ finally
+ {
+ // If this implementation is part of Begin/EndXx, then the EndXx method will handle
+ // finishing the async operation. However, if this is part of XxAsync, then there won't
+ // be an end method, and this task is responsible for cleaning up.
+ if (!thisTask._apm)
+ {
+ thisTask._stream.FinishTrackingAsyncOperation();
+ }
+
+ thisTask.ClearBeginState(); // just to help alleviate some memory pressure
+ }
+ }, state, this, buffer, offset, count, callback);
+
+ // Schedule it
+ if (semaphoreTask != null)
+ RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
+ else
+ RunReadWriteTask(asyncResult);
+
+ return asyncResult; // return it
+ }
+
+ private void RunReadWriteTaskWhenReady(Task asyncWaiter, ReadWriteTask readWriteTask)
+ {
+ Debug.Assert(readWriteTask != null);
+ Debug.Assert(asyncWaiter != null);
+
+ // If the wait has already completed, run the task.
+ if (asyncWaiter.IsCompleted)
+ {
+ Debug.Assert(asyncWaiter.IsCompletedSuccessfully, "The semaphore wait should always complete successfully.");
+ RunReadWriteTask(readWriteTask);
+ }
+ else // Otherwise, wait for our turn, and then run the task.
+ {
+ asyncWaiter.ContinueWith((t, state) =>
+ {
+ Debug.Assert(t.IsCompletedSuccessfully, "The semaphore wait should always complete successfully.");
+ var rwt = (ReadWriteTask)state;
+ rwt._stream.RunReadWriteTask(rwt); // RunReadWriteTask(readWriteTask);
+ }, readWriteTask, default, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+ }
+
+ private void RunReadWriteTask(ReadWriteTask readWriteTask)
+ {
+ Debug.Assert(readWriteTask != null);
+ Debug.Assert(_activeReadWriteTask == null, "Expected no other readers or writers");
+
+ // Schedule the task. ScheduleAndStart must happen after the write to _activeReadWriteTask to avoid a race.
+ // Internally, we're able to directly call ScheduleAndStart rather than Start, avoiding
+ // two interlocked operations. However, if ReadWriteTask is ever changed to use
+ // a cancellation token, this should be changed to use Start.
+ _activeReadWriteTask = readWriteTask; // store the task so that EndXx can validate it's given the right one
+ readWriteTask.m_taskScheduler = TaskScheduler.Default;
+ readWriteTask.ScheduleAndStart(needsProtection: false);
+ }
+
+ private void FinishTrackingAsyncOperation()
+ {
+ _activeReadWriteTask = null;
+ Debug.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here.");
+ _asyncActiveSemaphore.Release();
+ }
+
+ public virtual void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ var writeTask = _activeReadWriteTask;
+ if (writeTask == null)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple);
+ }
+ else if (writeTask != asyncResult)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple);
+ }
+ else if (writeTask._isRead)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple);
+ }
+
+ try
+ {
+ writeTask.GetAwaiter().GetResult(); // block until completion, then propagate any exceptions
+ Debug.Assert(writeTask.Status == TaskStatus.RanToCompletion);
+ }
+ finally
+ {
+ FinishTrackingAsyncOperation();
+ }
+ }
+
+ // Task used by BeginRead / BeginWrite to do Read / Write asynchronously.
+ // A single instance of this task serves four purposes:
+ // 1. The work item scheduled to run the Read / Write operation
+ // 2. The state holding the arguments to be passed to Read / Write
+ // 3. The IAsyncResult returned from BeginRead / BeginWrite
+ // 4. The completion action that runs to invoke the user-provided callback.
+ // This last item is a bit tricky. Before the AsyncCallback is invoked, the
+ // IAsyncResult must have completed, so we can't just invoke the handler
+ // from within the task, since it is the IAsyncResult, and thus it's not
+ // yet completed. Instead, we use AddCompletionAction to install this
+ // task as its own completion handler. That saves the need to allocate
+ // a separate completion handler, it guarantees that the task will
+ // have completed by the time the handler is invoked, and it allows
+ // the handler to be invoked synchronously upon the completion of the
+ // task. This all enables BeginRead / BeginWrite to be implemented
+ // with a single allocation.
+ private sealed class ReadWriteTask : Task<int>, ITaskCompletionAction
+ {
+ internal readonly bool _isRead;
+ internal readonly bool _apm; // true if this is from Begin/EndXx; false if it's from XxAsync
+ internal Stream _stream;
+ internal byte[] _buffer;
+ internal readonly int _offset;
+ internal readonly int _count;
+ private AsyncCallback _callback;
+ private ExecutionContext _context;
+
+ internal void ClearBeginState() // Used to allow the args to Read/Write to be made available for GC
+ {
+ _stream = null;
+ _buffer = null;
+ }
+
+ public ReadWriteTask(
+ bool isRead,
+ bool apm,
+ Func<object, int> function, object state,
+ Stream stream, byte[] buffer, int offset, int count, AsyncCallback callback) :
+ base(function, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach)
+ {
+ Debug.Assert(function != null);
+ Debug.Assert(stream != null);
+ Debug.Assert(buffer != null);
+
+ // Store the arguments
+ _isRead = isRead;
+ _apm = apm;
+ _stream = stream;
+ _buffer = buffer;
+ _offset = offset;
+ _count = count;
+
+ // If a callback was provided, we need to:
+ // - Store the user-provided handler
+ // - Capture an ExecutionContext under which to invoke the handler
+ // - Add this task as its own completion handler so that the Invoke method
+ // will run the callback when this task completes.
+ if (callback != null)
+ {
+ _callback = callback;
+ _context = ExecutionContext.Capture();
+ base.AddCompletionAction(this);
+ }
+ }
+
+ private static void InvokeAsyncCallback(object completedTask)
+ {
+ var rwc = (ReadWriteTask)completedTask;
+ var callback = rwc._callback;
+ rwc._callback = null;
+ callback(rwc);
+ }
+
+ private static ContextCallback s_invokeAsyncCallback;
+
+ void ITaskCompletionAction.Invoke(Task completingTask)
+ {
+ // Get the ExecutionContext. If there is none, just run the callback
+ // directly, passing in the completed task as the IAsyncResult.
+ // If there is one, process it with ExecutionContext.Run.
+ var context = _context;
+ if (context == null)
+ {
+ var callback = _callback;
+ _callback = null;
+ callback(completingTask);
+ }
+ else
+ {
+ _context = null;
+
+ var invokeAsyncCallback = s_invokeAsyncCallback;
+ if (invokeAsyncCallback == null) s_invokeAsyncCallback = invokeAsyncCallback = InvokeAsyncCallback; // benign race condition
+
+ ExecutionContext.RunInternal(context, invokeAsyncCallback, this);
+ }
+ }
+
+ bool ITaskCompletionAction.InvokeMayRunArbitraryCode { get { return true; } }
+ }
+
+ public Task WriteAsync(byte[] buffer, int offset, int count)
+ {
+ return WriteAsync(buffer, offset, count, CancellationToken.None);
+ }
+
+ public virtual Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ // If cancellation was requested, bail early with an already completed task.
+ // Otherwise, return a task that represents the Begin/End methods.
+ return cancellationToken.IsCancellationRequested
+ ? Task.FromCanceled(cancellationToken)
+ : BeginEndWriteAsync(buffer, offset, count);
+ }
+
+ public virtual ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
+ {
+ return new ValueTask(WriteAsync(array.Array, array.Offset, array.Count, cancellationToken));
+ }
+ else
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ buffer.Span.CopyTo(sharedBuffer);
+ return new ValueTask(FinishWriteAsync(WriteAsync(sharedBuffer, 0, buffer.Length, cancellationToken), sharedBuffer));
+ }
+ }
+
+ private async Task FinishWriteAsync(Task writeTask, byte[] localBuffer)
+ {
+ try
+ {
+ await writeTask.ConfigureAwait(false);
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(localBuffer);
+ }
+ }
+
+ private Task BeginEndWriteAsync(byte[] buffer, int offset, int count)
+ {
+ if (!HasOverriddenBeginEndWrite())
+ {
+ // If the Stream does not override Begin/EndWrite, then we can take an optimized path
+ // that skips an extra layer of tasks / IAsyncResults.
+ return (Task)BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
+ }
+
+ // Otherwise, we need to wrap calls to Begin/EndWrite to ensure we use the derived type's functionality.
+ return TaskFactory<VoidTaskResult>.FromAsyncTrim(
+ this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
+ (stream, args, callback, state) => stream.BeginWrite(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
+ (stream, asyncResult) => // cached by compiler
+ {
+ stream.EndWrite(asyncResult);
+ return default;
+ });
+ }
+
+ public abstract long Seek(long offset, SeekOrigin origin);
+
+ public abstract void SetLength(long value);
+
+ public abstract int Read(byte[] buffer, int offset, int count);
+
+ public virtual int Read(Span<byte> buffer)
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ try
+ {
+ int numRead = Read(sharedBuffer, 0, buffer.Length);
+ if ((uint)numRead > buffer.Length)
+ {
+ throw new IOException(SR.IO_StreamTooLong);
+ }
+ new Span<byte>(sharedBuffer, 0, numRead).CopyTo(buffer);
+ return numRead;
+ }
+ finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
+ }
+
+ // Reads one byte from the stream by calling Read(byte[], int, int).
+ // Will return an unsigned byte cast to an int or -1 on end of stream.
+ // This implementation does not perform well because it allocates a new
+ // byte[] each time you call it, and should be overridden by any
+ // subclass that maintains an internal buffer. Then, it can help perf
+ // significantly for people who are reading one byte at a time.
+ public virtual int ReadByte()
+ {
+ byte[] oneByteArray = new byte[1];
+ int r = Read(oneByteArray, 0, 1);
+ if (r == 0)
+ return -1;
+ return oneByteArray[0];
+ }
+
+ public abstract void Write(byte[] buffer, int offset, int count);
+
+ public virtual void Write(ReadOnlySpan<byte> buffer)
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ try
+ {
+ buffer.CopyTo(sharedBuffer);
+ Write(sharedBuffer, 0, buffer.Length);
+ }
+ finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
+ }
+
+ // Writes one byte from the stream by calling Write(byte[], int, int).
+ // This implementation does not perform well because it allocates a new
+ // byte[] each time you call it, and should be overridden by any
+ // subclass that maintains an internal buffer. Then, it can help perf
+ // significantly for people who are writing one byte at a time.
+ public virtual void WriteByte(byte value)
+ {
+ byte[] oneByteArray = new byte[1];
+ oneByteArray[0] = value;
+ Write(oneByteArray, 0, 1);
+ }
+
+ public static Stream Synchronized(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+ if (stream is SyncStream)
+ return stream;
+
+ return new SyncStream(stream);
+ }
+
+ [Obsolete("Do not call or override this method.")]
+ protected virtual void ObjectInvariant()
+ {
+ }
+
+ internal IAsyncResult BlockingBeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ // To avoid a race with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread and do the IO synchronously.
+ // This can't perform well - use a different approach.
+ SynchronousAsyncResult asyncResult;
+ try
+ {
+ int numRead = Read(buffer, offset, count);
+ asyncResult = new SynchronousAsyncResult(numRead, state);
+ }
+ catch (IOException ex)
+ {
+ asyncResult = new SynchronousAsyncResult(ex, state, isWrite: false);
+ }
+
+ if (callback != null)
+ {
+ callback(asyncResult);
+ }
+
+ return asyncResult;
+ }
+
+ internal static int BlockingEndRead(IAsyncResult asyncResult)
+ {
+ return SynchronousAsyncResult.EndRead(asyncResult);
+ }
+
+ internal IAsyncResult BlockingBeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread and do the IO synchronously.
+ // This can't perform well - use a different approach.
+ SynchronousAsyncResult asyncResult;
+ try
+ {
+ Write(buffer, offset, count);
+ asyncResult = new SynchronousAsyncResult(state);
+ }
+ catch (IOException ex)
+ {
+ asyncResult = new SynchronousAsyncResult(ex, state, isWrite: true);
+ }
+
+ if (callback != null)
+ {
+ callback(asyncResult);
+ }
+
+ return asyncResult;
+ }
+
+ internal static void BlockingEndWrite(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult.EndWrite(asyncResult);
+ }
+
+ private sealed class NullStream : Stream
+ {
+ private static readonly Task<int> s_zeroTask = Task.FromResult(0);
+
+ internal NullStream() { }
+
+ public override bool CanRead => true;
+
+ public override bool CanWrite => true;
+
+ public override bool CanSeek => true;
+
+ public override long Length => 0;
+
+ public override long Position
+ {
+ get { return 0; }
+ set { }
+ }
+
+ public override void CopyTo(Stream destination, int bufferSize)
+ {
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ // After we validate arguments this is a nop.
+ }
+
+ public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ // Validate arguments here for compat, since previously this method
+ // was inherited from Stream (which did check its arguments).
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // Do nothing - we don't want NullStream singleton (static) to be closable
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ if (!CanRead) throw Error.GetReadNotSupported();
+
+ return BlockingBeginRead(buffer, offset, count, callback, state);
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ return BlockingEndRead(asyncResult);
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ if (!CanWrite) throw Error.GetWriteNotSupported();
+
+ return BlockingBeginWrite(buffer, offset, count, callback, state);
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ BlockingEndWrite(asyncResult);
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return 0;
+ }
+
+ public override int Read(Span<byte> buffer)
+ {
+ return 0;
+ }
+
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return s_zeroTask;
+ }
+
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ return new ValueTask<int>(0);
+ }
+
+ public override int ReadByte()
+ {
+ return -1;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ }
+
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ }
+
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ new ValueTask(Task.FromCanceled(cancellationToken)) :
+ default;
+ }
+
+ public override void WriteByte(byte value)
+ {
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return 0;
+ }
+
+ public override void SetLength(long length)
+ {
+ }
+ }
+
+
+ /// <summary>Used as the IAsyncResult object when using asynchronous IO methods on the base Stream class.</summary>
+ private sealed class SynchronousAsyncResult : IAsyncResult
+ {
+ private readonly object _stateObject;
+ private readonly bool _isWrite;
+ private ManualResetEvent _waitHandle;
+ private ExceptionDispatchInfo _exceptionInfo;
+
+ private bool _endXxxCalled;
+ private int _bytesRead;
+
+ internal SynchronousAsyncResult(int bytesRead, object asyncStateObject)
+ {
+ _bytesRead = bytesRead;
+ _stateObject = asyncStateObject;
+ //_isWrite = false;
+ }
+
+ internal SynchronousAsyncResult(object asyncStateObject)
+ {
+ _stateObject = asyncStateObject;
+ _isWrite = true;
+ }
+
+ internal SynchronousAsyncResult(Exception ex, object asyncStateObject, bool isWrite)
+ {
+ _exceptionInfo = ExceptionDispatchInfo.Capture(ex);
+ _stateObject = asyncStateObject;
+ _isWrite = isWrite;
+ }
+
+ public bool IsCompleted
+ {
+ // We never hand out objects of this type to the user before the synchronous IO completed:
+ get { return true; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get
+ {
+ return LazyInitializer.EnsureInitialized(ref _waitHandle, () => new ManualResetEvent(true));
+ }
+ }
+
+ public object AsyncState
+ {
+ get { return _stateObject; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return true; }
+ }
+
+ internal void ThrowIfError()
+ {
+ if (_exceptionInfo != null)
+ _exceptionInfo.Throw();
+ }
+
+ internal static int EndRead(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
+ if (ar == null || ar._isWrite)
+ throw new ArgumentException(SR.Arg_WrongAsyncResult);
+
+ if (ar._endXxxCalled)
+ throw new ArgumentException(SR.InvalidOperation_EndReadCalledMultiple);
+
+ ar._endXxxCalled = true;
+
+ ar.ThrowIfError();
+ return ar._bytesRead;
+ }
+
+ internal static void EndWrite(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
+ if (ar == null || !ar._isWrite)
+ throw new ArgumentException(SR.Arg_WrongAsyncResult);
+
+ if (ar._endXxxCalled)
+ throw new ArgumentException(SR.InvalidOperation_EndWriteCalledMultiple);
+
+ ar._endXxxCalled = true;
+
+ ar.ThrowIfError();
+ }
+ } // class SynchronousAsyncResult
+
+
+ // SyncStream is a wrapper around a stream that takes
+ // a lock for every operation making it thread safe.
+ private sealed class SyncStream : Stream, IDisposable
+ {
+ private Stream _stream;
+
+ internal SyncStream(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+ _stream = stream;
+ }
+
+ public override bool CanRead => _stream.CanRead;
+
+ public override bool CanWrite => _stream.CanWrite;
+
+ public override bool CanSeek => _stream.CanSeek;
+
+ public override bool CanTimeout => _stream.CanTimeout;
+
+ public override long Length
+ {
+ get
+ {
+ lock (_stream)
+ {
+ return _stream.Length;
+ }
+ }
+ }
+
+ public override long Position
+ {
+ get
+ {
+ lock (_stream)
+ {
+ return _stream.Position;
+ }
+ }
+ set
+ {
+ lock (_stream)
+ {
+ _stream.Position = value;
+ }
+ }
+ }
+
+ public override int ReadTimeout
+ {
+ get
+ {
+ return _stream.ReadTimeout;
+ }
+ set
+ {
+ _stream.ReadTimeout = value;
+ }
+ }
+
+ public override int WriteTimeout
+ {
+ get
+ {
+ return _stream.WriteTimeout;
+ }
+ set
+ {
+ _stream.WriteTimeout = value;
+ }
+ }
+
+ // In the off chance that some wrapped stream has different
+ // semantics for Close vs. Dispose, let's preserve that.
+ public override void Close()
+ {
+ lock (_stream)
+ {
+ try
+ {
+ _stream.Close();
+ }
+ finally
+ {
+ base.Dispose(true);
+ }
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ lock (_stream)
+ {
+ try
+ {
+ // Explicitly pick up a potentially methodimpl'ed Dispose
+ if (disposing)
+ ((IDisposable)_stream).Dispose();
+ }
+ finally
+ {
+ base.Dispose(disposing);
+ }
+ }
+ }
+
+ public override void Flush()
+ {
+ lock (_stream)
+ _stream.Flush();
+ }
+
+ public override int Read(byte[] bytes, int offset, int count)
+ {
+ lock (_stream)
+ return _stream.Read(bytes, offset, count);
+ }
+
+ public override int Read(Span<byte> buffer)
+ {
+ lock (_stream)
+ return _stream.Read(buffer);
+ }
+
+ public override int ReadByte()
+ {
+ lock (_stream)
+ return _stream.ReadByte();
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+#if CORERT
+ throw new NotImplementedException(); // TODO: https://github.com/dotnet/corert/issues/3251
+#else
+ bool overridesBeginRead = _stream.HasOverriddenBeginEndRead();
+
+ lock (_stream)
+ {
+ // If the Stream does have its own BeginRead implementation, then we must use that override.
+ // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
+ // which ensures only one asynchronous operation does so with an asynchronous wait rather
+ // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
+ // the EndXx method for the outstanding async operation won't be able to acquire the lock on
+ // _stream due to this call blocked while holding the lock.
+ return overridesBeginRead ?
+ _stream.BeginRead(buffer, offset, count, callback, state) :
+ _stream.BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
+ }
+#endif
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ lock (_stream)
+ return _stream.EndRead(asyncResult);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ lock (_stream)
+ return _stream.Seek(offset, origin);
+ }
+
+ public override void SetLength(long length)
+ {
+ lock (_stream)
+ _stream.SetLength(length);
+ }
+
+ public override void Write(byte[] bytes, int offset, int count)
+ {
+ lock (_stream)
+ _stream.Write(bytes, offset, count);
+ }
+
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ lock (_stream)
+ _stream.Write(buffer);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ lock (_stream)
+ _stream.WriteByte(b);
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+#if CORERT
+ throw new NotImplementedException(); // TODO: https://github.com/dotnet/corert/issues/3251
+#else
+ bool overridesBeginWrite = _stream.HasOverriddenBeginEndWrite();
+
+ lock (_stream)
+ {
+ // If the Stream does have its own BeginWrite implementation, then we must use that override.
+ // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
+ // which ensures only one asynchronous operation does so with an asynchronous wait rather
+ // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
+ // the EndXx method for the outstanding async operation won't be able to acquire the lock on
+ // _stream due to this call blocked while holding the lock.
+ return overridesBeginWrite ?
+ _stream.BeginWrite(buffer, offset, count, callback, state) :
+ _stream.BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
+ }
+#endif
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ lock (_stream)
+ _stream.EndWrite(asyncResult);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs b/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs
index 22ec6e645..5c3cc9157 100644
--- a/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs
@@ -70,21 +70,21 @@ namespace System.IO
// We don't guarantee thread safety on StreamReader, but we should at
// least prevent users from trying to read anything while an Async
// read from the same thread is in progress.
- private volatile Task _asyncReadTask;
+ private Task _asyncReadTask = Task.CompletedTask;
private void CheckAsyncTaskInProgress()
{
// We are not locking the access to _asyncReadTask because this is not meant to guarantee thread safety.
// We are simply trying to deter calling any Read APIs while an async Read from the same thread is in progress.
-
- Task t = _asyncReadTask;
-
- if (t != null && !t.IsCompleted)
+ if (!_asyncReadTask.IsCompleted)
{
- throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+ ThrowAsyncIOInProgress();
}
}
+ private static void ThrowAsyncIOInProgress() =>
+ throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+
// StreamReader by default will ignore illegal UTF8 characters. We don't want to
// throw here because we want to be able to read ill-formed data without choking.
// The high level goal is to be tolerant of encoding errors when we read and very strict
@@ -1059,7 +1059,7 @@ namespace System.IO
// data read in, let's try writing directly to the user's buffer.
bool readToUserBuffer = false;
- Byte[] tmpByteBuffer = _byteBuffer;
+ byte[] tmpByteBuffer = _byteBuffer;
Stream tmpStream = _stream;
int count = buffer.Length;
@@ -1290,7 +1290,7 @@ namespace System.IO
{
_charLen = 0;
_charPos = 0;
- Byte[] tmpByteBuffer = _byteBuffer;
+ byte[] tmpByteBuffer = _byteBuffer;
Stream tmpStream = _stream;
if (!_checkPreamble)
diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
index a37624428..8d94ac60b 100644
--- a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@@ -44,19 +45,21 @@ namespace System.IO
// We don't guarantee thread safety on StreamWriter, but we should at
// least prevent users from trying to write anything while an Async
// write from the same thread is in progress.
- private volatile Task _asyncWriteTask;
+ private Task _asyncWriteTask = Task.CompletedTask;
private void CheckAsyncTaskInProgress()
{
// We are not locking the access to _asyncWriteTask because this is not meant to guarantee thread safety.
// We are simply trying to deter calling any Write APIs while an async Write from the same thread is in progress.
-
- Task t = _asyncWriteTask;
-
- if (t != null && !t.IsCompleted)
- throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+ if (!_asyncWriteTask.IsCompleted)
+ {
+ ThrowAsyncIOInProgress();
+ }
}
+ private static void ThrowAsyncIOInProgress() =>
+ throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+
// The high level goal is to be tolerant of encoding errors when we read and very strict
// when we write. Hence, default StreamWriter encoding will throw on encoding error.
// Note: when StreamWriter throws on invalid encoding chars (for ex, high surrogate character
@@ -323,14 +326,13 @@ namespace System.IO
}
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(char[] buffer)
{
- if (buffer != null)
- {
- WriteCore(buffer, _autoFlush);
- }
+ WriteSpan(buffer, appendNewLine: false);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(char[] buffer, int index, int count)
{
if (buffer == null)
@@ -350,14 +352,15 @@ namespace System.IO
throw new ArgumentException(SR.Argument_InvalidOffLen);
}
- WriteCore(new ReadOnlySpan<char>(buffer, index, count), _autoFlush);
+ WriteSpan(buffer.AsSpan(index, count), appendNewLine: false);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(ReadOnlySpan<char> buffer)
{
if (GetType() == typeof(StreamWriter))
{
- WriteCore(buffer, _autoFlush);
+ WriteSpan(buffer, appendNewLine: false);
}
else
{
@@ -367,7 +370,8 @@ namespace System.IO
}
}
- private unsafe void WriteCore(ReadOnlySpan<char> buffer, bool autoFlush)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private unsafe void WriteSpan(ReadOnlySpan<char> buffer, bool appendNewLine)
{
CheckAsyncTaskInProgress();
@@ -422,41 +426,47 @@ namespace System.IO
}
}
- if (autoFlush)
+ if (appendNewLine)
+ {
+ char[] coreNewLine = CoreNewLine;
+ for (int i = 0; i < coreNewLine.Length; i++) // Generally 1 (\n) or 2 (\r\n) iterations
+ {
+ if (_charPos == _charLen)
+ {
+ Flush(false, false);
+ }
+
+ _charBuffer[_charPos] = coreNewLine[i];
+ _charPos++;
+ }
+ }
+
+ if (_autoFlush)
{
Flush(true, false);
}
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(string value)
{
- if (value != null)
- {
- WriteCore(value.AsSpan(), _autoFlush);
- }
+ WriteSpan(value, appendNewLine: false);
}
- //
- // Optimize the most commonly used WriteLine overload. This optimization is important for System.Console in particular
- // because of it will make one WriteLine equal to one call to the OS instead of two in the common case.
- //
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void WriteLine(string value)
{
CheckAsyncTaskInProgress();
- if (value != null)
- {
- WriteCore(value.AsSpan(), autoFlush: false);
- }
- WriteCore(new ReadOnlySpan<char>(CoreNewLine), autoFlush: true);
+ WriteSpan(value, appendNewLine: true);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void WriteLine(ReadOnlySpan<char> value)
{
if (GetType() == typeof(StreamWriter))
{
CheckAsyncTaskInProgress();
- WriteCore(value, autoFlush: false);
- WriteCore(new ReadOnlySpan<char>(CoreNewLine), autoFlush: true);
+ WriteSpan(value, appendNewLine: true);
}
else
{
@@ -466,6 +476,123 @@ namespace System.IO
}
}
+ private void WriteFormatHelper(string format, ParamsArray args, bool appendNewLine)
+ {
+ StringBuilder sb =
+ StringBuilderCache.Acquire(format.Length + args.Length * 8)
+ .AppendFormatHelper(null, format, args);
+
+ StringBuilder.ChunkEnumerator chunks = sb.GetChunks();
+
+ bool more = chunks.MoveNext();
+ while (more)
+ {
+ ReadOnlySpan<char> current = chunks.Current.Span;
+ more = chunks.MoveNext();
+
+ // If final chunk, include the newline if needed
+ WriteSpan(current, appendNewLine: more ? false : appendNewLine);
+ }
+
+ StringBuilderCache.Release(sb);
+ }
+
+ public override void Write(string format, object arg0)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0);
+ }
+ }
+
+ public override void Write(string format, object arg0, object arg1)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0, arg1);
+ }
+ }
+
+ public override void Write(string format, object arg0, object arg1, object arg2)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1, arg2), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0, arg1, arg2);
+ }
+ }
+
+ public override void Write(string format, params object[] arg)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0, object arg1)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0, arg1);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0, object arg1, object arg2)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1, arg2), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0, arg1, arg2);
+ }
+ }
+
+ public override void WriteLine(string format, params object[] arg)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg);
+ }
+ }
+
#region Task based Async APIs
public override Task WriteAsync(char value)
{
@@ -955,7 +1082,7 @@ namespace System.IO
// to ensure performant access inside the state machine that corresponds this async method.
private static async Task FlushAsyncInternal(StreamWriter _this, bool flushStream, bool flushEncoder,
char[] charBuffer, int charPos, bool haveWrittenPreamble,
- Encoding encoding, Encoder encoder, Byte[] byteBuffer, Stream stream, CancellationToken cancellationToken)
+ Encoding encoding, Encoder encoder, byte[] byteBuffer, Stream stream, CancellationToken cancellationToken)
{
if (!haveWrittenPreamble)
{
diff --git a/src/System.Private.CoreLib/shared/System/IO/TextReader.cs b/src/System.Private.CoreLib/shared/System/IO/TextReader.cs
index eb94dd759..bb5b142bd 100644
--- a/src/System.Private.CoreLib/shared/System/IO/TextReader.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/TextReader.cs
@@ -207,7 +207,7 @@ namespace System.IO
#region Task based Async APIs
public virtual Task<string> ReadLineAsync()
{
- return Task<String>.Factory.StartNew(state =>
+ return Task<string>.Factory.StartNew(state =>
{
return ((TextReader)state).ReadLine();
},
@@ -251,7 +251,7 @@ namespace System.IO
return ReadAsyncInternal(new Memory<char>(buffer, index, count), default).AsTask();
}
- public virtual ValueTask<int> ReadAsync(Memory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual ValueTask<int> ReadAsync(Memory<char> buffer, CancellationToken cancellationToken = default) =>
new ValueTask<int>(MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
ReadAsync(array.Array, array.Offset, array.Count) :
Task<int>.Factory.StartNew(state =>
@@ -289,7 +289,7 @@ namespace System.IO
return ReadBlockAsyncInternal(new Memory<char>(buffer, index, count), default).AsTask();
}
- public virtual ValueTask<int> ReadBlockAsync(Memory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual ValueTask<int> ReadBlockAsync(Memory<char> buffer, CancellationToken cancellationToken = default) =>
new ValueTask<int>(MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
ReadBlockAsync(array.Array, array.Offset, array.Count) :
Task<int>.Factory.StartNew(state =>
diff --git a/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs b/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs
index 48e702be6..547c597f0 100644
--- a/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs
@@ -13,24 +13,24 @@ using System.Buffers;
namespace System.IO
{
// This abstract base class represents a writer that can write a sequential
- // stream of characters. A subclass must minimally implement the
+ // stream of characters. A subclass must minimally implement the
// Write(char) method.
//
- // This class is intended for character output, not bytes.
- // There are methods on the Stream class for writing bytes.
+ // This class is intended for character output, not bytes.
+ // There are methods on the Stream class for writing bytes.
public abstract partial class TextWriter : MarshalByRefObject, IDisposable
{
public static readonly TextWriter Null = new NullTextWriter();
- // We don't want to allocate on every TextWriter creation, so cache the char array.
+ // We don't want to allocate on every TextWriter creation, so cache the char array.
private static readonly char[] s_coreNewLine = Environment.NewLine.ToCharArray();
/// <summary>
- /// This is the 'NewLine' property expressed as a char[].
+ /// This is the 'NewLine' property expressed as a char[].
/// It is exposed to subclasses as a protected field for read-only
- /// purposes. You should only modify it by using the 'NewLine' property.
- /// In particular you should never modify the elements of the array
- /// as they are shared among many instances of TextWriter.
+ /// purposes. You should only modify it by using the 'NewLine' property.
+ /// In particular you should never modify the elements of the array
+ /// as they are shared among many instances of TextWriter.
/// </summary>
protected char[] CoreNewLine = s_coreNewLine;
private string CoreNewLineStr = Environment.NewLine;
@@ -94,7 +94,7 @@ namespace System.IO
/// <summary>
/// Returns the line terminator string used by this TextWriter. The default line
- /// terminator string is Environment.NewLine, which is platform specific.
+ /// terminator string is Environment.NewLine, which is platform specific.
/// On Windows this is a carriage return followed by a line feed ("\r\n").
/// On OSX and Linux this is a line feed ("\n").
/// </summary>
@@ -184,7 +184,7 @@ namespace System.IO
}
// Writes the text representation of a boolean to the text stream. This
- // method outputs either Boolean.TrueString or Boolean.FalseString.
+ // method outputs either bool.TrueString or bool.FalseString.
//
public virtual void Write(bool value)
{
@@ -193,7 +193,7 @@ namespace System.IO
// Writes the text representation of an integer to the text stream. The
// text representation of the given value is produced by calling the
- // Int32.ToString() method.
+ // int.ToString() method.
//
public virtual void Write(int value)
{
@@ -202,7 +202,7 @@ namespace System.IO
// Writes the text representation of an integer to the text stream. The
// text representation of the given value is produced by calling the
- // UInt32.ToString() method.
+ // uint.ToString() method.
//
[CLSCompliant(false)]
public virtual void Write(uint value)
@@ -212,16 +212,16 @@ namespace System.IO
// Writes the text representation of a long to the text stream. The
// text representation of the given value is produced by calling the
- // Int64.ToString() method.
+ // long.ToString() method.
//
public virtual void Write(long value)
{
Write(value.ToString(FormatProvider));
}
- // Writes the text representation of an unsigned long to the text
- // stream. The text representation of the given value is produced
- // by calling the UInt64.ToString() method.
+ // Writes the text representation of an unsigned long to the text
+ // stream. The text representation of the given value is produced
+ // by calling the ulong.ToString() method.
//
[CLSCompliant(false)]
public virtual void Write(ulong value)
@@ -231,7 +231,7 @@ namespace System.IO
// Writes the text representation of a float to the text stream. The
// text representation of the given value is produced by calling the
- // Float.toString(float) method.
+ // float.ToString(float) method.
//
public virtual void Write(float value)
{
@@ -240,7 +240,7 @@ namespace System.IO
// Writes the text representation of a double to the text stream. The
// text representation of the given value is produced by calling the
- // Double.toString(double) method.
+ // double.ToString(double) method.
//
public virtual void Write(double value)
{
@@ -283,33 +283,48 @@ namespace System.IO
}
}
+ /// <summary>
+ /// Equivalent to Write(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+ public virtual void Write(StringBuilder value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ foreach (ReadOnlyMemory<char> chunk in value.GetChunks())
+ Write(chunk);
+ }
+
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, object arg0)
{
Write(string.Format(FormatProvider, format, arg0));
}
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, object arg0, object arg1)
{
Write(string.Format(FormatProvider, format, arg0, arg1));
}
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, object arg0, object arg1, object arg2)
{
Write(string.Format(FormatProvider, format, arg0, arg1, arg2));
}
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, params object[] arg)
{
Write(string.Format(FormatProvider, format, arg));
@@ -383,7 +398,7 @@ namespace System.IO
WriteLine();
}
- // Writes the text representation of an unsigned integer followed by
+ // Writes the text representation of an unsigned integer followed by
// a line terminator to the text stream.
//
[CLSCompliant(false)]
@@ -402,7 +417,7 @@ namespace System.IO
WriteLine();
}
- // Writes the text representation of an unsigned long followed by
+ // Writes the text representation of an unsigned long followed by
// a line terminator to the text stream.
//
[CLSCompliant(false)]
@@ -447,6 +462,16 @@ namespace System.IO
Write(CoreNewLineStr);
}
+ /// <summary>
+ /// Equivalent to WriteLine(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ public virtual void WriteLine(StringBuilder value)
+ {
+ Write(value);
+ WriteLine();
+ }
+
// Writes the text representation of an object followed by a line
// terminator to the text stream.
//
@@ -472,33 +497,33 @@ namespace System.IO
}
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, object arg0)
{
WriteLine(string.Format(FormatProvider, format, arg0));
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, object arg0, object arg1)
{
WriteLine(string.Format(FormatProvider, format, arg0, arg1));
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, object arg0, object arg1, object arg2)
{
WriteLine(string.Format(FormatProvider, format, arg0, arg1, arg2));
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, params object[] arg)
{
WriteLine(string.Format(FormatProvider, format, arg));
@@ -527,6 +552,27 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
+ /// <summary>
+ /// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+ public virtual Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ return
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
+ value == null ? Task.CompletedTask :
+ WriteAsyncCore(value, cancellationToken);
+
+ async Task WriteAsyncCore(StringBuilder sb, CancellationToken ct)
+ {
+ foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ {
+ await WriteAsync(chunk, ct).ConfigureAwait(false);
+ }
+ }
+ }
+
public Task WriteAsync(char[] buffer)
{
if (buffer == null)
@@ -548,7 +594,8 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
- public virtual Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
WriteAsync(array.Array, array.Offset, array.Count) :
Task.Factory.StartNew(state =>
@@ -579,6 +626,28 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
+ /// <summary>
+ /// Equivalent to WriteLineAsync(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+ public virtual Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ return
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
+ value == null ? WriteAsync(CoreNewLine, cancellationToken) :
+ WriteLineAsyncCore(value, cancellationToken);
+
+ async Task WriteLineAsyncCore(StringBuilder sb, CancellationToken ct)
+ {
+ foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ {
+ await WriteAsync(chunk, ct).ConfigureAwait(false);
+ }
+ await WriteAsync(CoreNewLine, ct).ConfigureAwait(false);
+ }
+ }
+
public Task WriteLineAsync(char[] buffer)
{
if (buffer == null)
@@ -600,7 +669,8 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
- public virtual Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
WriteLineAsync(array.Array, array.Offset, array.Count) :
Task.Factory.StartNew(state =>
@@ -739,12 +809,15 @@ namespace System.IO
public override void Write(double value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
- public override void Write(Decimal value) => _out.Write(value);
+ public override void Write(decimal value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Write(string value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override void Write(StringBuilder value) => _out.Write(value);
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override void Write(object value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
@@ -799,6 +872,9 @@ namespace System.IO
public override void WriteLine(string value) => _out.WriteLine(value);
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override void WriteLine(StringBuilder value) => _out.WriteLine(value);
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override void WriteLine(object value) => _out.WriteLine(value);
[MethodImpl(MethodImplOptions.Synchronized)]
@@ -832,6 +908,13 @@ namespace System.IO
}
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ Write(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override Task WriteAsync(char[] buffer, int index, int count)
{
Write(buffer, index, count);
@@ -853,6 +936,13 @@ namespace System.IO
}
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ WriteLine(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override Task WriteLineAsync(char[] buffer, int index, int count)
{
WriteLine(buffer, index, count);
diff --git a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs
index d1a13156a..d4af4cfee 100644
--- a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs
@@ -47,7 +47,7 @@ namespace System.IO
private long _offset;
private FileAccess _access;
private bool _isOpen;
- private Task<Int32> _lastReadTask; // The last successful task returned from ReadAsync
+ private Task<int> _lastReadTask; // The last successful task returned from ReadAsync
/// <summary>
/// Creates a closed stream.
@@ -379,22 +379,22 @@ namespace System.IO
return ReadCore(new Span<byte>(buffer, offset, count));
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
if (GetType() == typeof(UnmanagedMemoryStream))
{
- return ReadCore(destination);
+ return ReadCore(buffer);
}
else
{
// UnmanagedMemoryStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
// to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
// should use the behavior of Read(byte[],int,int) overload.
- return base.Read(destination);
+ return base.Read(buffer);
}
}
- internal int ReadCore(Span<byte> destination)
+ internal int ReadCore(Span<byte> buffer)
{
EnsureNotClosed();
EnsureReadable();
@@ -403,7 +403,7 @@ namespace System.IO
// changes our position after we decide we can read some bytes.
long pos = Interlocked.Read(ref _position);
long len = Interlocked.Read(ref _length);
- long n = Math.Min(len - pos, destination.Length);
+ long n = Math.Min(len - pos, buffer.Length);
if (n <= 0)
{
return 0;
@@ -418,7 +418,7 @@ namespace System.IO
unsafe
{
- fixed (byte* pBuffer = &MemoryMarshal.GetReference(destination))
+ fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer))
{
if (_buffer != null)
{
@@ -456,7 +456,7 @@ namespace System.IO
/// <param name="count">Maximum number of bytes to read.</param>
/// <param name="cancellationToken">Token that can be used to cancel this operation.</param>
/// <returns>Task that can be used to access the number of bytes actually read.</returns>
- public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -468,27 +468,27 @@ namespace System.IO
throw new ArgumentException(SR.Argument_InvalidOffLen);
if (cancellationToken.IsCancellationRequested)
- return Task.FromCanceled<Int32>(cancellationToken);
+ return Task.FromCanceled<int>(cancellationToken);
try
{
- Int32 n = Read(buffer, offset, count);
- Task<Int32> t = _lastReadTask;
+ int n = Read(buffer, offset, count);
+ Task<int> t = _lastReadTask;
return (t != null && t.Result == n) ? t : (_lastReadTask = Task.FromResult<Int32>(n));
}
catch (Exception ex)
{
Debug.Assert(!(ex is OperationCanceledException));
- return Task.FromException<Int32>(ex);
+ return Task.FromException<int>(ex);
}
}
/// <summary>
/// Reads bytes from stream and puts them into the buffer
/// </summary>
- /// <param name="destination">Buffer to read the bytes to.</param>
+ /// <param name="buffer">Buffer to read the bytes to.</param>
/// <param name="cancellationToken">Token that can be used to cancel this operation.</param>
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -510,9 +510,9 @@ namespace System.IO
// something other than an array and this is an UnmanagedMemoryStream-derived type that doesn't override Read(Span<byte>) will
// it then fall back to doing the ArrayPool/copy behavior.
return new ValueTask<int>(
- MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> destinationArray) ?
+ MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> destinationArray) ?
Read(destinationArray.Array, destinationArray.Offset, destinationArray.Count) :
- Read(destination.Span));
+ Read(buffer.Span));
}
catch (Exception ex)
{
@@ -659,29 +659,29 @@ namespace System.IO
WriteCore(new Span<byte>(buffer, offset, count));
}
- public override void Write(ReadOnlySpan<byte> source)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
if (GetType() == typeof(UnmanagedMemoryStream))
{
- WriteCore(source);
+ WriteCore(buffer);
}
else
{
// UnmanagedMemoryStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
// to this Write(Span<byte>) overload being introduced. In that case, this Write(Span<byte>) overload
// should use the behavior of Write(byte[],int,int) overload.
- base.Write(source);
+ base.Write(buffer);
}
}
- internal unsafe void WriteCore(ReadOnlySpan<byte> source)
+ internal unsafe void WriteCore(ReadOnlySpan<byte> buffer)
{
EnsureNotClosed();
EnsureWriteable();
long pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
long len = Interlocked.Read(ref _length);
- long n = pos + source.Length;
+ long n = pos + buffer.Length;
// Check for overflow
if (n < 0)
{
@@ -709,12 +709,12 @@ namespace System.IO
}
}
- fixed (byte* pBuffer = &MemoryMarshal.GetReference(source))
+ fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer))
{
if (_buffer != null)
{
long bytesLeft = _capacity - pos;
- if (bytesLeft < source.Length)
+ if (bytesLeft < buffer.Length)
{
throw new ArgumentException(SR.Arg_BufferTooSmall);
}
@@ -724,7 +724,7 @@ namespace System.IO
try
{
_buffer.AcquirePointer(ref pointer);
- Buffer.Memcpy(pointer + pos + _offset, pBuffer, source.Length);
+ Buffer.Memcpy(pointer + pos + _offset, pBuffer, buffer.Length);
}
finally
{
@@ -736,7 +736,7 @@ namespace System.IO
}
else
{
- Buffer.Memcpy(_mem + pos, pBuffer, source.Length);
+ Buffer.Memcpy(_mem + pos, pBuffer, buffer.Length);
}
}
@@ -752,7 +752,7 @@ namespace System.IO
/// <param name="count">Number of bytes to write.</param>
/// <param name="cancellationToken">Token that can be used to cancel the operation.</param>
/// <returns>Task that can be awaited </returns>
- public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -783,7 +783,7 @@ namespace System.IO
/// </summary>
/// <param name="buffer">Buffer that will be written.</param>
/// <param name="cancellationToken">Token that can be used to cancel the operation.</param>
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -794,13 +794,13 @@ namespace System.IO
{
// See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>).
// Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
- if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> sourceArray))
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> sourceArray))
{
Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count);
}
else
{
- Write(source.Span);
+ Write(buffer.Span);
}
return default;
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
index f34c3c413..9a598951e 100644
--- a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
@@ -71,7 +71,7 @@ namespace System.IO
public override bool TryGetBuffer(out ArraySegment<byte> buffer)
{
- buffer = default(ArraySegment<byte>);
+ buffer = default;
return false;
}
@@ -112,9 +112,9 @@ namespace System.IO
return _unmanagedStream.Read(buffer, offset, count);
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
- return _unmanagedStream.Read(destination);
+ return _unmanagedStream.Read(buffer);
}
public override int ReadByte()
@@ -139,9 +139,9 @@ namespace System.IO
_unmanagedStream.Write(buffer, offset, count);
}
- public override void Write(ReadOnlySpan<byte> source)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
- _unmanagedStream.Write(source);
+ _unmanagedStream.Write(buffer);
}
public override void WriteByte(byte value)
@@ -160,7 +160,7 @@ namespace System.IO
stream.Write(buffer, 0, buffer.Length);
}
- public override void SetLength(Int64 value)
+ public override void SetLength(long value)
{
// This was probably meant to call _unmanagedStream.SetLength(value), but it was forgotten in V.4.0.
// Now this results in a call to the base which touches the underlying array which is never actually used.
@@ -169,7 +169,7 @@ namespace System.IO
}
- public override Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
+ public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
// The parameter checks must be in sync with the base version:
if (destination == null)
@@ -201,25 +201,25 @@ namespace System.IO
}
- public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _unmanagedStream.ReadAsync(buffer, offset, count, cancellationToken);
}
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
- return _unmanagedStream.ReadAsync(destination, cancellationToken);
+ return _unmanagedStream.ReadAsync(buffer, cancellationToken);
}
- public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _unmanagedStream.WriteAsync(buffer, offset, count, cancellationToken);
}
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
- return _unmanagedStream.WriteAsync(source, cancellationToken);
+ return _unmanagedStream.WriteAsync(buffer, cancellationToken);
}
} // class UnmanagedMemoryStreamWrapper
} // namespace
diff --git a/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs b/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs
index b8b305776..cf1d94cba 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs
@@ -2,14 +2,12 @@
// 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;
using System.Runtime.InteropServices;
namespace System.IO
{
/// <summary>
- /// Provides static methods for converting from Win32 errors codes to exceptions, HRESULTS and error messages.
+ /// Provides static methods for converting from Win32 errors codes to exceptions, HRESULTS and error messages.
/// </summary>
internal static class Win32Marshal
{
@@ -22,94 +20,84 @@ namespace System.IO
#endif
/// <summary>
- /// Converts, resetting it, the last Win32 error into a corresponding <see cref="Exception"/> object.
+ /// Converts, resetting it, the last Win32 error into a corresponding <see cref="Exception"/> object, optionally
+ /// including the specified path in the error message.
/// </summary>
- internal static Exception GetExceptionForLastWin32Error()
- {
- int errorCode = Marshal.GetLastWin32Error();
- return GetExceptionForWin32Error(errorCode, string.Empty);
- }
-
- /// <summary>
- /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object.
- /// </summary>
- internal static Exception GetExceptionForWin32Error(int errorCode)
- {
- return GetExceptionForWin32Error(errorCode, string.Empty);
- }
+ internal static Exception GetExceptionForLastWin32Error(string path = "")
+ => GetExceptionForWin32Error(Marshal.GetLastWin32Error(), path);
/// <summary>
- /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object, optionally
- /// including the specified path in the error message.
+ /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object, optionally
+ /// including the specified path in the error message.
/// </summary>
- internal static Exception GetExceptionForWin32Error(int errorCode, string path)
+ internal static Exception GetExceptionForWin32Error(int errorCode, string path = "")
{
switch (errorCode)
{
case Interop.Errors.ERROR_FILE_NOT_FOUND:
- if (path.Length == 0)
- return new FileNotFoundException(SR.IO_FileNotFound);
- else
- return new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path);
-
+ return new FileNotFoundException(
+ string.IsNullOrEmpty(path) ? SR.IO_FileNotFound : SR.Format(SR.IO_FileNotFound_FileName, path), path);
case Interop.Errors.ERROR_PATH_NOT_FOUND:
- if (path.Length == 0)
- return new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName);
- else
- return new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path));
-
+ return new DirectoryNotFoundException(
+ string.IsNullOrEmpty(path) ? SR.IO_PathNotFound_NoPathName : SR.Format(SR.IO_PathNotFound_Path, path));
case Interop.Errors.ERROR_ACCESS_DENIED:
- if (path.Length == 0)
- return new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName);
- else
- return new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path));
-
+ return new UnauthorizedAccessException(
+ string.IsNullOrEmpty(path) ? SR.UnauthorizedAccess_IODenied_NoPathName : SR.Format(SR.UnauthorizedAccess_IODenied_Path, path));
case Interop.Errors.ERROR_ALREADY_EXISTS:
- if (path.Length == 0)
+ if (string.IsNullOrEmpty(path))
goto default;
-
return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode));
-
case Interop.Errors.ERROR_FILENAME_EXCED_RANGE:
- if (path.Length == 0)
- return new PathTooLongException(SR.IO_PathTooLong);
- else
- return new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path));
-
- case Interop.Errors.ERROR_INVALID_DRIVE:
- throw new DriveNotFoundException(SR.Format(SR.IO_DriveNotFound_Drive, path));
-
- case Interop.Errors.ERROR_INVALID_PARAMETER:
- return new IOException(Interop.Kernel32.GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
-
+ return new PathTooLongException(
+ string.IsNullOrEmpty(path) ? SR.IO_PathTooLong : SR.Format(SR.IO_PathTooLong_Path, path));
case Interop.Errors.ERROR_SHARING_VIOLATION:
- if (path.Length == 0)
- return new IOException(SR.IO_SharingViolation_NoFileName, MakeHRFromErrorCode(errorCode));
- else
- return new IOException(SR.Format(SR.IO_SharingViolation_File, path), MakeHRFromErrorCode(errorCode));
-
+ return new IOException(
+ string.IsNullOrEmpty(path) ? SR.IO_SharingViolation_NoFileName : SR.Format(SR.IO_SharingViolation_File, path),
+ MakeHRFromErrorCode(errorCode));
case Interop.Errors.ERROR_FILE_EXISTS:
- if (path.Length == 0)
+ if (string.IsNullOrEmpty(path))
goto default;
-
return new IOException(SR.Format(SR.IO_FileExists_Name, path), MakeHRFromErrorCode(errorCode));
-
case Interop.Errors.ERROR_OPERATION_ABORTED:
return new OperationCanceledException();
-
+ case Interop.Errors.ERROR_INVALID_PARAMETER:
default:
- return new IOException(Interop.Kernel32.GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
+ return new IOException(
+ string.IsNullOrEmpty(path) ? GetMessage(errorCode) : $"{GetMessage(errorCode)} : '{path}'",
+ MakeHRFromErrorCode(errorCode));
}
}
/// <summary>
- /// Returns a HRESULT for the specified Win32 error code.
+ /// If not already an HRESULT, returns an HRESULT for the specified Win32 error code.
/// </summary>
internal static int MakeHRFromErrorCode(int errorCode)
{
- Debug.Assert((0xFFFF0000 & errorCode) == 0, "This is an HRESULT, not an error code!");
+ // Don't convert it if it is already an HRESULT
+ if ((0xFFFF0000 & errorCode) != 0)
+ return errorCode;
return unchecked(((int)0x80070000) | errorCode);
}
+
+ /// <summary>
+ /// Returns a Win32 error code for the specified HRESULT if it came from FACILITY_WIN32
+ /// If not, returns the HRESULT unchanged
+ /// </summary>
+ internal static int TryMakeWin32ErrorCodeFromHR(int hr)
+ {
+ if ((0xFFFF0000 & hr) == 0x80070000)
+ {
+ // Win32 error, Win32Marshal.GetExceptionForWin32Error expects the Win32 format
+ hr &= 0x0000FFFF;
+ }
+
+ return hr;
+ }
+
+ /// <summary>
+ /// Returns a string message for the specified Win32 error code.
+ /// </summary>
+ internal static string GetMessage(int errorCode) => Interop.Kernel32.GetMessage(errorCode);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs b/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs
index b6d93ef56..aadc94231 100644
--- a/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs
+++ b/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
- public IndexOutOfRangeException(String message)
+ public IndexOutOfRangeException(string message)
: base(message)
{
HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
- public IndexOutOfRangeException(String message, Exception innerException)
+ public IndexOutOfRangeException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INDEXOUTOFRANGE;
diff --git a/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs b/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs
index 4822028f8..4c4bf242e 100644
--- a/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs
+++ b/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs
@@ -16,13 +16,13 @@ namespace System
HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
- public InsufficientExecutionStackException(String message)
+ public InsufficientExecutionStackException(string message)
: base(message)
{
HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
- public InsufficientExecutionStackException(String message, Exception innerException)
+ public InsufficientExecutionStackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
diff --git a/src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs b/src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs
new file mode 100644
index 000000000..baa5c9e24
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs
@@ -0,0 +1,51 @@
+// 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.Runtime.Serialization;
+
+namespace System
+{
+ /// <summary>
+ /// Purpose: The exception class for running out of memory
+ /// but most likely in a non-fatal way that shouldn't
+ /// be affected by escalation policy. Use this for cases
+ /// like MemoryFailPoint or a TryAllocate method, where you
+ /// expect OOM's with no shared state corruption and you
+ /// want to recover from these errors.
+ /// </summary>
+ [Serializable]
+#if !MONO
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public sealed class InsufficientMemoryException : OutOfMemoryException
+ {
+ public InsufficientMemoryException() : base(
+#if CORECLR
+ GetMessageFromNativeResources(ExceptionMessageKind.OutOfMemory)
+#else
+ SR.Arg_OutOfMemoryException
+#endif
+ )
+ {
+ HResult = HResults.COR_E_INSUFFICIENTMEMORY;
+ }
+
+ public InsufficientMemoryException(string message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_INSUFFICIENTMEMORY;
+ }
+
+ public InsufficientMemoryException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ HResult = HResults.COR_E_INSUFFICIENTMEMORY;
+ }
+
+ private InsufficientMemoryException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Int16.cs b/src/System.Private.CoreLib/shared/System/Int16.cs
index fecc87e9f..497329976 100644
--- a/src/System.Private.CoreLib/shared/System/Int16.cs
+++ b/src/System.Private.CoreLib/shared/System/Int16.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Int16 : IComparable, IConvertible, IFormattable, IComparable<Int16>, IEquatable<Int16>, ISpanFormattable
+ public readonly struct Int16 : IComparable, IConvertible, IFormattable, IComparable<short>, IEquatable<short>, ISpanFormattable
{
- private short m_value; // Do not rename (binary serialization)
+ private readonly short m_value; // Do not rename (binary serialization)
public const short MaxValue = (short)0x7FFF;
public const short MinValue = unchecked((short)0x8000);
@@ -25,37 +25,37 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Int16, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Int16)
+ if (value is short)
{
- return m_value - ((Int16)value).m_value;
+ return m_value - ((short)value).m_value;
}
throw new ArgumentException(SR.Arg_MustBeInt16);
}
- public int CompareTo(Int16 value)
+ public int CompareTo(short value)
{
return m_value - value;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Int16))
+ if (!(obj is short))
{
return false;
}
- return m_value == ((Int16)obj).m_value;
+ return m_value == ((short)obj).m_value;
}
[NonVersionable]
- public bool Equals(Int16 obj)
+ public bool Equals(short obj)
{
return m_value == obj;
}
@@ -67,22 +67,22 @@ namespace System
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return ToString(format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x'))
{
@@ -103,26 +103,26 @@ namespace System
return Number.TryFormatInt32(m_value, format, provider, destination, out charsWritten);
}
- public static short Parse(String s)
+ public static short Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static short Parse(String s, NumberStyles style)
+ public static short Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, style, NumberFormatInfo.CurrentInfo);
}
- public static short Parse(String s, IFormatProvider provider)
+ public static short Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
- public static short Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static short Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -151,7 +151,7 @@ namespace System
// for negative numbers
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || (i > UInt16.MaxValue))
+ if ((i < 0) || (i > ushort.MaxValue))
{
throw new OverflowException(SR.Overflow_Int16);
}
@@ -162,7 +162,7 @@ namespace System
return (short)i;
}
- public static bool TryParse(String s, out Int16 result)
+ public static bool TryParse(string s, out short result)
{
if (s == null)
{
@@ -178,7 +178,7 @@ namespace System
return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int16 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out short result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -197,7 +197,7 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Int16 result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out short result)
{
result = 0;
int i;
@@ -210,11 +210,11 @@ namespace System
// for negative numbers
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || i > UInt16.MaxValue)
+ if ((i < 0) || i > ushort.MaxValue)
{
return false;
}
- result = (Int16)i;
+ result = (short)i;
return true;
}
@@ -222,7 +222,7 @@ namespace System
{
return false;
}
- result = (Int16)i;
+ result = (short)i;
return true;
}
@@ -296,7 +296,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -306,7 +306,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int16", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Int32.cs b/src/System.Private.CoreLib/shared/System/Int32.cs
index b573e950e..1d0aefe73 100644
--- a/src/System.Private.CoreLib/shared/System/Int32.cs
+++ b/src/System.Private.CoreLib/shared/System/Int32.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Int32 : IComparable, IConvertible, IFormattable, IComparable<Int32>, IEquatable<Int32>, ISpanFormattable
+ public readonly struct Int32 : IComparable, IConvertible, IFormattable, IComparable<int>, IEquatable<int>, ISpanFormattable
{
- private int m_value; // Do not rename (binary serialization)
+ private readonly int m_value; // Do not rename (binary serialization)
public const int MaxValue = 0x7fffffff;
public const int MinValue = unchecked((int)0x80000000);
@@ -28,13 +28,13 @@ namespace System
// null is considered to be less than any instance, hence returns positive number
// If object is not of type Int32, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Int32)
+ if (value is int)
{
// NOTE: Cannot use return (_value - value) as this causes a wrap
// around in cases where _value - value > MaxValue.
@@ -55,17 +55,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Int32))
+ if (!(obj is int))
{
return false;
}
- return m_value == ((Int32)obj).m_value;
+ return m_value == ((int)obj).m_value;
}
[NonVersionable]
- public bool Equals(Int32 obj)
+ public bool Equals(int obj)
{
return m_value == obj;
}
@@ -76,22 +76,22 @@ namespace System
return m_value;
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt32(m_value, null, null);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatInt32(m_value, format, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(m_value, null, provider);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatInt32(m_value, format, provider);
}
@@ -101,13 +101,13 @@ namespace System
return Number.TryFormatInt32(m_value, format, provider, destination, out charsWritten);
}
- public static int Parse(String s)
+ public static int Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static int Parse(String s, NumberStyles style)
+ public static int Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -118,7 +118,7 @@ namespace System
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
- public static int Parse(String s, IFormatProvider provider)
+ public static int Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -128,7 +128,7 @@ namespace System
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
- public static int Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static int Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -144,7 +144,7 @@ namespace System
// Parses an integer from a String. Returns false rather
// than throwing exceptin if input is invalid
//
- public static bool TryParse(String s, out Int32 result)
+ public static bool TryParse(string s, out int result)
{
if (s == null)
{
@@ -163,7 +163,7 @@ namespace System
// Parses an integer from a String in the given style. Returns false rather
// than throwing exceptin if input is invalid
//
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int32 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out int result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -251,7 +251,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -261,7 +261,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int32", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Int64.cs b/src/System.Private.CoreLib/shared/System/Int64.cs
index 0bcca8730..62c9ffd4f 100644
--- a/src/System.Private.CoreLib/shared/System/Int64.cs
+++ b/src/System.Private.CoreLib/shared/System/Int64.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Int64 : IComparable, IConvertible, IFormattable, IComparable<Int64>, IEquatable<Int64>, ISpanFormattable
+ public readonly struct Int64 : IComparable, IConvertible, IFormattable, IComparable<long>, IEquatable<long>, ISpanFormattable
{
- private long m_value; // Do not rename (binary serialization)
+ private readonly long m_value; // Do not rename (binary serialization)
public const long MaxValue = 0x7fffffffffffffffL;
public const long MinValue = unchecked((long)0x8000000000000000L);
@@ -25,13 +25,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Int64, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Int64)
+ if (value is long)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -43,7 +43,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeInt64);
}
- public int CompareTo(Int64 value)
+ public int CompareTo(long value)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -52,17 +52,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Int64))
+ if (!(obj is long))
{
return false;
}
- return m_value == ((Int64)obj).m_value;
+ return m_value == ((long)obj).m_value;
}
[NonVersionable]
- public bool Equals(Int64 obj)
+ public bool Equals(long obj)
{
return m_value == obj;
}
@@ -73,22 +73,22 @@ namespace System
return (unchecked((int)((long)m_value)) ^ (int)(m_value >> 32));
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt64(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt64(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatInt64(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatInt64(m_value, format, provider);
}
@@ -98,20 +98,20 @@ namespace System
return Number.TryFormatInt64(m_value, format, provider, destination, out charsWritten);
}
- public static long Parse(String s)
+ public static long Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static long Parse(String s, NumberStyles style)
+ public static long Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt64(s, style, NumberFormatInfo.CurrentInfo);
}
- public static long Parse(String s, IFormatProvider provider)
+ public static long Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -122,7 +122,7 @@ namespace System
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
- public static long Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static long Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -135,7 +135,7 @@ namespace System
return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static Boolean TryParse(String s, out Int64 result)
+ public static bool TryParse(string s, out long result)
{
if (s == null)
{
@@ -151,7 +151,7 @@ namespace System
return Number.TryParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Int64 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out long result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -239,7 +239,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -249,7 +249,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int64", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/IntPtr.cs b/src/System.Private.CoreLib/shared/System/IntPtr.cs
index 45c2ded16..d23742fa7 100644
--- a/src/System.Private.CoreLib/shared/System/IntPtr.cs
+++ b/src/System.Private.CoreLib/shared/System/IntPtr.cs
@@ -17,13 +17,13 @@ namespace System
{
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct IntPtr : IEquatable<IntPtr>, ISerializable
+ public readonly struct IntPtr : IEquatable<IntPtr>, ISerializable
{
// WARNING: We allow diagnostic tools to directly inspect this member (_value).
// See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
// Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
// Get in touch with the diagnostics team if you have questions.
- unsafe private void* _value; // Do not rename (binary serialization)
+ private readonly unsafe void* _value; // Do not rename (binary serialization)
[Intrinsic]
public static readonly IntPtr Zero;
@@ -72,7 +72,7 @@ namespace System
info.AddValue("value", ToInt64());
}
- public unsafe override bool Equals(Object obj)
+ public unsafe override bool Equals(object obj)
{
if (obj is IntPtr)
{
@@ -81,9 +81,9 @@ namespace System
return false;
}
- unsafe bool IEquatable<IntPtr>.Equals(IntPtr value)
+ unsafe bool IEquatable<IntPtr>.Equals(IntPtr other)
{
- return _value == value._value;
+ return _value == other._value;
}
public unsafe override int GetHashCode()
@@ -217,6 +217,9 @@ namespace System
[CLSCompliant(false)]
[Intrinsic]
[NonVersionable]
+#if PROJECTN
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+#endif
public unsafe void* ToPointer()
{
return _value;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidCastException.cs b/src/System.Private.CoreLib/shared/System/InvalidCastException.cs
index 055643278..cb6036aeb 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidCastException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidCastException.cs
@@ -22,19 +22,19 @@ namespace System
HResult = HResults.COR_E_INVALIDCAST;
}
- public InvalidCastException(String message)
+ public InvalidCastException(string message)
: base(message)
{
HResult = HResults.COR_E_INVALIDCAST;
}
- public InvalidCastException(String message, Exception innerException)
+ public InvalidCastException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INVALIDCAST;
}
- public InvalidCastException(String message, int errorCode)
+ public InvalidCastException(string message, int errorCode)
: base(message)
{
HResult = errorCode;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs b/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs
index 62c222af4..9fffbec43 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_INVALIDOPERATION;
}
- public InvalidOperationException(String message)
+ public InvalidOperationException(string message)
: base(message)
{
HResult = HResults.COR_E_INVALIDOPERATION;
}
- public InvalidOperationException(String message, Exception innerException)
+ public InvalidOperationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INVALIDOPERATION;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs b/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs
index c8047c548..62a14f911 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_INVALIDPROGRAM;
}
- public InvalidProgramException(String message)
+ public InvalidProgramException(string message)
: base(message)
{
HResult = HResults.COR_E_INVALIDPROGRAM;
}
- public InvalidProgramException(String message, Exception inner)
+ public InvalidProgramException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_INVALIDPROGRAM;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs b/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs
index 25b155e8d..1bbb7e067 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs
@@ -14,12 +14,12 @@ namespace System
{
}
- public InvalidTimeZoneException(String message)
+ public InvalidTimeZoneException(string message)
: base(message)
{
}
- public InvalidTimeZoneException(String message, Exception innerException)
+ public InvalidTimeZoneException(string message, Exception innerException)
: base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/shared/System/Lazy.cs b/src/System.Private.CoreLib/shared/System/Lazy.cs
index 6410c2e28..02122ca05 100644
--- a/src/System.Private.CoreLib/shared/System/Lazy.cs
+++ b/src/System.Private.CoreLib/shared/System/Lazy.cs
@@ -119,7 +119,7 @@ namespace System
default:
Debug.Fail("Invalid logic; State should always have a valid value");
- return default(LazyThreadSafetyMode);
+ return default;
}
}
@@ -454,7 +454,7 @@ namespace System
{
if (!IsValueCreated)
{
- return default(T);
+ return default;
}
return _value;
}
diff --git a/src/System.Private.CoreLib/shared/System/Marvin.cs b/src/System.Private.CoreLib/shared/System/Marvin.cs
new file mode 100644
index 000000000..d25a244c9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Marvin.cs
@@ -0,0 +1,143 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif
+
+namespace System
+{
+ internal static class Marvin
+ {
+ /// <summary>
+ /// Compute a Marvin hash and collapse it into a 32-bit hash.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int ComputeHash32(ReadOnlySpan<byte> data, ulong seed) => ComputeHash32(ref MemoryMarshal.GetReference(data), data.Length, seed);
+
+ /// <summary>
+ /// Compute a Marvin hash and collapse it into a 32-bit hash.
+ /// </summary>
+ public static int ComputeHash32(ref byte data, int count, ulong seed)
+ {
+ nuint ucount = (nuint)count;
+ uint p0 = (uint)seed;
+ uint p1 = (uint)(seed >> 32);
+
+ nuint byteOffset = 0;
+
+ while (ucount >= 8)
+ {
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
+ Block(ref p0, ref p1);
+
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset + 4));
+ Block(ref p0, ref p1);
+
+ byteOffset += 8;
+ ucount -= 8;
+ }
+
+ switch (ucount)
+ {
+ case 4:
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
+ Block(ref p0, ref p1);
+ goto case 0;
+
+ case 0:
+ p0 += 0x80u;
+ break;
+
+ case 5:
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
+ byteOffset += 4;
+ Block(ref p0, ref p1);
+ goto case 1;
+
+ case 1:
+ p0 += 0x8000u | Unsafe.AddByteOffset(ref data, byteOffset);
+ break;
+
+ case 6:
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
+ byteOffset += 4;
+ Block(ref p0, ref p1);
+ goto case 2;
+
+ case 2:
+ p0 += 0x800000u | Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref data, byteOffset));
+ break;
+
+ case 7:
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
+ byteOffset += 4;
+ Block(ref p0, ref p1);
+ goto case 3;
+
+ case 3:
+ p0 += 0x80000000u | (((uint)(Unsafe.AddByteOffset(ref data, byteOffset + 2))) << 16)| (uint)(Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref data, byteOffset)));
+ break;
+
+ default:
+ Debug.Fail("Should not get here.");
+ break;
+ }
+
+ Block(ref p0, ref p1);
+ Block(ref p0, ref p1);
+
+ return (int)(p1 ^ p0);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void Block(ref uint rp0, ref uint rp1)
+ {
+ uint p0 = rp0;
+ uint p1 = rp1;
+
+ p1 ^= p0;
+ p0 = _rotl(p0, 20);
+
+ p0 += p1;
+ p1 = _rotl(p1, 9);
+
+ p1 ^= p0;
+ p0 = _rotl(p0, 27);
+
+ p0 += p1;
+ p1 = _rotl(p1, 19);
+
+ rp0 = p0;
+ rp1 = p1;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static uint _rotl(uint value, int shift)
+ {
+ // This is expected to be optimized into a single rol (or ror with negated shift value) instruction
+ return (value << shift) | (value >> (32 - shift));
+ }
+
+ public static ulong DefaultSeed { get; } = GenerateSeed();
+
+ private static unsafe ulong GenerateSeed()
+ {
+#if MONO
+ return 839433921;
+#else
+ ulong seed;
+ Interop.GetRandomBytes((byte*)&seed, sizeof(ulong));
+ return seed;
+#endif
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Math.cs b/src/System.Private.CoreLib/shared/System/Math.cs
index a175103f8..ef46869e2 100644
--- a/src/System.Private.CoreLib/shared/System/Math.cs
+++ b/src/System.Private.CoreLib/shared/System/Math.cs
@@ -123,15 +123,25 @@ namespace System
public static long DivRem(long a, long b, out long result)
{
- // TODO https://github.com/dotnet/coreclr/issues/3439:
- // Restore to using % and / when the JIT is able to eliminate one of the idivs.
- // In the meantime, a * and - is measurably faster than an extra /.
-
long div = a / b;
result = a - (div * b);
return div;
}
+ internal static uint DivRem(uint a, uint b, out uint result)
+ {
+ uint div = a / b;
+ result = a - (div * b);
+ return div;
+ }
+
+ internal static ulong DivRem(ulong a, ulong b, out ulong result)
+ {
+ ulong div = a / b;
+ result = a - (div * b);
+ return div;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal Ceiling(decimal d)
{
diff --git a/src/System.Private.CoreLib/shared/System/MemberAccessException.cs b/src/System.Private.CoreLib/shared/System/MemberAccessException.cs
index dfea52dbe..0cf1e0fbe 100644
--- a/src/System.Private.CoreLib/shared/System/MemberAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/MemberAccessException.cs
@@ -31,13 +31,13 @@ namespace System
// message, its HRESULT set to COR_E_ACCESS,
// and its ExceptionInfo reference set to null.
//
- public MemberAccessException(String message)
+ public MemberAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_MEMBERACCESS;
}
- public MemberAccessException(String message, Exception inner)
+ public MemberAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MEMBERACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/Memory.cs b/src/System.Private.CoreLib/shared/System/Memory.cs
index fca015f5e..1a7556720 100644
--- a/src/System.Private.CoreLib/shared/System/Memory.cs
+++ b/src/System.Private.CoreLib/shared/System/Memory.cs
@@ -8,9 +8,8 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
-#if !FEATURE_PORTABLE_SPAN
+
using Internal.Runtime.CompilerServices;
-#endif // FEATURE_PORTABLE_SPAN
namespace System
{
@@ -18,23 +17,26 @@ namespace System
/// Memory represents a contiguous region of arbitrary memory similar to <see cref="Span{T}"/>.
/// Unlike <see cref="Span{T}"/>, it is not a byref-like type.
/// </summary>
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
+ [DebuggerDisplay("{ToString(),raw}")]
public readonly struct Memory<T>
{
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
// as code uses Unsafe.As to cast between them.
// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
- // if (_index >> 31) == 1, object _object is an OwnedMemory<T>
- // else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
+ // if (_index >> 31) == 1, object _object is an MemoryManager<T>
+ // else, object _object is a T[] or a string.
+ // if (_length >> 31) == 1, _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
+ // else, Pin() needs to allocate a new GCHandle to pin the object.
+ // It can only be a string if the Memory<T> was created by
// using unsafe / marshaling code to reinterpret a ReadOnlyMemory<char> wrapped around a string as
// a Memory<T>.
private readonly object _object;
private readonly int _index;
private readonly int _length;
- private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+ private const int RemoveFlagsBitMask = 0x7FFFFFFF;
/// <summary>
/// Creates a new memory over the entirety of the target array.
@@ -110,22 +112,61 @@ namespace System
_length = length;
}
- // Constructor for internal use only.
+ /// <summary>
+ /// Creates a new memory from a memory manager that provides specific method implementations beginning
+ /// at 0 index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="manager">The memory manager.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="length"/> is negative.
+ /// </exception>
+ /// <remarks>For internal infrastructure only</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Memory(OwnedMemory<T> owner, int index, int length)
+ internal Memory(MemoryManager<T> manager, int length)
{
- // No validation performed; caller must provide any necessary validation.
- _object = owner;
- _index = index | (1 << 31); // Before using _index, check if _index < 0, then 'and' it with RemoveOwnedFlagBitMask
+ Debug.Assert(manager != null);
+
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _object = manager;
+ _index = (1 << 31); // Mark as MemoryManager type
+ // Before using _index, check if _index < 0, then 'and' it with RemoveFlagsBitMask
+ _length = length;
+ }
+
+ /// <summary>
+ /// Creates a new memory from a memory manager that provides specific method implementations beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="manager">The memory manager.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or <paramref name="length"/> is negative.
+ /// </exception>
+ /// <remarks>For internal infrastructure only</remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal Memory(MemoryManager<T> manager, int start, int length)
+ {
+ Debug.Assert(manager != null);
+
+ if (length < 0 || start < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _object = manager;
+ _index = start | (1 << 31); // Mark as MemoryManager type
+ // Before using _index, check if _index < 0, then 'and' it with RemoveFlagsBitMask
_length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Memory(object obj, int index, int length)
+ internal Memory(object obj, int start, int length)
{
// No validation performed; caller must provide any necessary validation.
_object = obj;
- _index = index;
+ _index = start;
_length = length;
}
@@ -137,7 +178,7 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Memory{T}"/>
/// </summary>
- public static implicit operator Memory<T>(ArraySegment<T> arraySegment) => new Memory<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator Memory<T>(ArraySegment<T> segment) => new Memory<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Defines an implicit conversion of a <see cref="Memory{T}"/> to a <see cref="ReadOnlyMemory{T}"/>
@@ -145,9 +186,6 @@ namespace System
public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) =>
Unsafe.As<Memory<T>, ReadOnlyMemory<T>>(ref memory);
- //Debugger Display = {T[length]}
- private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
-
/// <summary>
/// Returns an empty <see cref="Memory{T}"/>
/// </summary>
@@ -156,12 +194,25 @@ namespace System
/// <summary>
/// The number of items in the memory.
/// </summary>
- public int Length => _length;
+ public int Length => _length & RemoveFlagsBitMask;
/// <summary>
/// Returns true if Length is 0.
/// </summary>
- public bool IsEmpty => _length == 0;
+ public bool IsEmpty => (_length & RemoveFlagsBitMask) == 0;
+
+ /// <summary>
+ /// For <see cref="Memory{Char}"/>, returns a new instance of string that represents the characters pointed to by the memory.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+ /// </summary>
+ public override string ToString()
+ {
+ if (typeof(T) == typeof(char))
+ {
+ return (_object is string str) ? str.Substring(_index, _length & RemoveFlagsBitMask) : Span.ToString();
+ }
+ return string.Format("System.Memory<{0}>[{1}]", typeof(T).Name, _length & RemoveFlagsBitMask);
+ }
/// <summary>
/// Forms a slice out of the given memory, beginning at 'start'.
@@ -173,12 +224,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Memory<T> Slice(int start)
{
- if ((uint)start > (uint)_length)
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = capturedLength & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
}
- return new Memory<T>(_object, _index + start, _length - start);
+ // It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned.
+ return new Memory<T>(_object, _index + start, capturedLength - start);
}
/// <summary>
@@ -192,12 +247,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Memory<T> Slice(int start, int length)
{
- if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = capturedLength & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start))
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
- return new Memory<T>(_object, _index + start, length);
+ // Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned).
+ return new Memory<T>(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask));
}
/// <summary>
@@ -210,24 +269,23 @@ namespace System
{
if (_index < 0)
{
- return ((OwnedMemory<T>)_object).Span.Slice(_index & RemoveOwnedFlagBitMask, _length);
+ Debug.Assert(_length >= 0);
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).GetSpan().Slice(_index & RemoveFlagsBitMask, _length);
}
else if (typeof(T) == typeof(char) && _object is string s)
{
+ Debug.Assert(_length >= 0);
// This is dangerous, returning a writable span for a string that should be immutable.
// However, we need to handle the case where a ReadOnlyMemory<char> was created from a string
// and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
// in which case that's the dangerous operation performed by the dev, and we're just following
// suit here to make it work as best as possible.
-#if FEATURE_PORTABLE_SPAN
- return new Span<T>(Unsafe.As<Pinnable<T>>(s), MemoryExtensions.StringAdjustment, s.Length).Slice(_index, _length);
-#else
return new Span<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
-#endif // FEATURE_PORTABLE_SPAN
}
else if (_object != null)
{
- return new Span<T>((T[])_object, _index, _length);
+ return new Span<T>((T[])_object, _index, _length & RemoveFlagsBitMask);
}
else
{
@@ -260,53 +318,47 @@ namespace System
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span);
/// <summary>
- /// Returns a handle for the array.
- /// <param name="pin">If pin is true, the GC will not move the array and hence its address can be taken</param>
+ /// Creates a handle for the memory.
+ /// The GC will not move the memory until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
+ /// <exception cref="System.ArgumentException">
+ /// An instance with nonprimitive (non-blittable) members cannot be pinned.
+ /// </exception>
/// </summary>
- public unsafe MemoryHandle Retain(bool pin = false)
+ public unsafe MemoryHandle Pin()
{
- MemoryHandle memoryHandle = default;
- if (pin)
+ if (_index < 0)
{
- if (_index < 0)
- {
- memoryHandle = ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>());
- }
- else if (typeof(T) == typeof(char) && _object is string s)
- {
- // This case can only happen if a ReadOnlyMemory<char> was created around a string
- // and then that was cast to a Memory<char> using unsafe / marshaling code. This needs
- // to work, however, so that code that uses a single Memory<char> field to store either
- // a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and
- // used for interop purposes.
- GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
- void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
- }
- else if (_object is T[] array)
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).Pin((_index & RemoveFlagsBitMask));
+ }
+ else if (typeof(T) == typeof(char) && _object is string s)
+ {
+ // This case can only happen if a ReadOnlyMemory<char> was created around a string
+ // and then that was cast to a Memory<char> using unsafe / marshaling code. This needs
+ // to work, however, so that code that uses a single Memory<char> field to store either
+ // a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and
+ // used for interop purposes.
+ GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
+ return new MemoryHandle(pointer, handle);
+ }
+ else if (_object is T[] array)
+ {
+ // Array is already pre-pinned
+ if (_length < 0)
{
- var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
+ return new MemoryHandle(pointer);
}
- }
- else
- {
- if (_index < 0)
+ else
{
- ((OwnedMemory<T>)_object).Retain();
- memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+ return new MemoryHandle(pointer, handle);
}
}
- return memoryHandle;
+ return default;
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs b/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs
index b1ed88199..6ab6e5065 100644
--- a/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs
+++ b/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Runtime.InteropServices;
namespace System
{
@@ -22,31 +21,6 @@ namespace System
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
- public T[] Items
- {
- // This is a work around since we cannot use _memory.ToArray() due to
- // https://devdiv.visualstudio.com/DevDiv/_workitems?id=286592
- get
- {
- if (MemoryMarshal.TryGetArray(_memory, out ArraySegment<T> segment))
- {
- T[] array = new T[_memory.Length];
- Array.Copy(segment.Array, segment.Offset, array, 0, array.Length);
- return array;
- }
-
- if (typeof(T) == typeof(char) &&
- MemoryMarshal.TryGetString((ReadOnlyMemory<char>)(object)_memory, out string text, out int start, out int length))
- {
- return (T[])(object)text.Substring(start, length).ToCharArray();
- }
-
-#if FEATURE_PORTABLE_SPAN
- return SpanHelpers.PerTypeValues<T>.EmptyArray;
-#else
- return Array.Empty<T>();
-#endif // FEATURE_PORTABLE_SPAN
- }
- }
+ public T[] Items => _memory.ToArray();
}
}
diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
index 56dd203e1..e86ca4fcd 100644
--- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
@@ -28,81 +28,93 @@ namespace System
}
/// <summary>
- /// Determines whether this <paramref name="span"/> and the specified <paramref name="value"/> span have the same characters
+ /// Determines whether this <paramref name="span"/> and the specified <paramref name="other"/> span have the same characters
/// when compared using the specified <paramref name="comparisonType"/> option.
/// <param name="span">The source span.</param>
- /// <param name="value">The value to compare with the source span.</param>
- /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
+ /// <param name="other">The value to compare with the source span.</param>
+ /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="other"/> are compared.</param>
/// </summary>
- public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
+ public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.None) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.CompareOptionNone(span, other) == 0);
case StringComparison.CurrentCultureIgnoreCase:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.IgnoreCase) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.CompareOptionIgnoreCase(span, other) == 0);
case StringComparison.InvariantCulture:
- return (CompareInfo.Invariant.Compare(span, value, CompareOptions.None) == 0);
+ return (CompareInfo.Invariant.CompareOptionNone(span, other) == 0);
case StringComparison.InvariantCultureIgnoreCase:
- return (CompareInfo.Invariant.Compare(span, value, CompareOptions.IgnoreCase) == 0);
+ return (CompareInfo.Invariant.CompareOptionIgnoreCase(span, other) == 0);
case StringComparison.Ordinal:
- if (span.Length != value.Length)
- return false;
- if (value.Length == 0) // span.Length == value.Length == 0
- return true;
- return span.SequenceEqual(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487
+ return EqualsOrdinal(span, other);
case StringComparison.OrdinalIgnoreCase:
- if (span.Length != value.Length)
- return false;
- if (value.Length == 0) // span.Length == value.Length == 0
- return true;
- return (CompareInfo.CompareOrdinalIgnoreCase(span, value) == 0);
+ return EqualsOrdinalIgnoreCase(span, other);
}
Debug.Fail("StringComparison outside range");
return false;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool EqualsOrdinal(this ReadOnlySpan<char> span, ReadOnlySpan<char> value)
+ {
+ if (span.Length != value.Length)
+ return false;
+ if (value.Length == 0) // span.Length == value.Length == 0
+ return true;
+ return span.SequenceEqual(value);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> span, ReadOnlySpan<char> value)
+ {
+ if (span.Length != value.Length)
+ return false;
+ if (value.Length == 0) // span.Length == value.Length == 0
+ return true;
+ return CompareInfo.EqualsOrdinalIgnoreCase(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), span.Length);
+ }
+
/// <summary>
- /// Compares the specified <paramref name="span"/> and <paramref name="value"/> using the specified <paramref name="comparisonType"/>,
+ /// Compares the specified <paramref name="span"/> and <paramref name="other"/> using the specified <paramref name="comparisonType"/>,
/// and returns an integer that indicates their relative position in the sort order.
/// <param name="span">The source span.</param>
- /// <param name="value">The value to compare with the source span.</param>
- /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
+ /// <param name="other">The value to compare with the source span.</param>
+ /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="other"/> are compared.</param>
/// </summary>
- public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
+ public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.None);
+ return CultureInfo.CurrentCulture.CompareInfo.CompareOptionNone(span, other);
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.CompareOptionIgnoreCase(span, other);
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.Compare(span, value, CompareOptions.None);
+ return CompareInfo.Invariant.CompareOptionNone(span, other);
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.Compare(span, value, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.CompareOptionIgnoreCase(span, other);
case StringComparison.Ordinal:
- if (span.Length == 0 || value.Length == 0)
- return span.Length - value.Length;
- return string.CompareOrdinal(span, value);
+ if (span.Length == 0 || other.Length == 0)
+ return span.Length - other.Length;
+ return string.CompareOrdinal(span, other);
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.CompareOrdinalIgnoreCase(span, value);
+ return CompareInfo.CompareOrdinalIgnoreCase(span, other);
}
Debug.Fail("StringComparison outside range");
@@ -117,7 +129,7 @@ namespace System
/// </summary>
public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
if (value.Length == 0)
{
@@ -129,29 +141,66 @@ namespace System
return -1;
}
+ if (GlobalizationMode.Invariant)
+ {
+ return CompareInfo.InvariantIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
+ }
+
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return SpanHelpers.IndexOfCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
case StringComparison.CurrentCultureIgnoreCase:
- return SpanHelpers.IndexOfCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return SpanHelpers.IndexOfCultureHelper(span, value, CompareInfo.Invariant);
-
case StringComparison.InvariantCultureIgnoreCase:
- return SpanHelpers.IndexOfCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant);
+ return CompareInfo.Invariant.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
- case StringComparison.Ordinal:
- return SpanHelpers.IndexOfOrdinalHelper(span, value, ignoreCase: false);
+ default:
+ Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
+ return CompareInfo.Invariant.IndexOfOrdinal(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
+ }
+ }
- case StringComparison.OrdinalIgnoreCase:
- return SpanHelpers.IndexOfOrdinalHelper(span, value, ignoreCase: true);
+ /// <summary>
+ /// Reports the zero-based index of the last occurrence of the specified <paramref name="value"/> in the current <paramref name="span"/>.
+ /// <param name="span">The source span.</param>
+ /// <param name="value">The value to seek within the source span.</param>
+ /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
+ /// </summary>
+ public static int LastIndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
+ {
+ string.CheckStringComparison(comparisonType);
+
+ if (value.Length == 0)
+ {
+ return span.Length > 0 ? span.Length - 1 : 0;
}
- Debug.Fail("StringComparison outside range");
- return -1;
+ if (span.Length == 0)
+ {
+ return -1;
+ }
+
+ if (GlobalizationMode.Invariant)
+ {
+ return CompareInfo.InvariantIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None, fromBeginning: false);
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.LastIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
+
+ default:
+ Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
+ return CompareInfo.Invariant.LastIndexOfOrdinal(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
+ }
}
/// <summary>
@@ -163,6 +212,7 @@ namespace System
/// <param name="culture">An object that supplies culture-specific casing rules.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
/// <exception cref="System.ArgumentNullException">
/// Thrown when <paramref name="culture"/> is null.
/// </exception>
@@ -176,7 +226,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- culture.TextInfo.ToLowerAsciiInvariant(source, destination);
+ TextInfo.ToLowerAsciiInvariant(source, destination);
else
culture.TextInfo.ChangeCase(source, destination, toUpper: false);
return source.Length;
@@ -190,6 +240,7 @@ namespace System
/// <param name="destination">The destination span which contains the transformed characters.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination)
{
// Assuming that changing case does not affect length
@@ -197,7 +248,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- CultureInfo.InvariantCulture.TextInfo.ToLowerAsciiInvariant(source, destination);
+ TextInfo.ToLowerAsciiInvariant(source, destination);
else
CultureInfo.InvariantCulture.TextInfo.ChangeCase(source, destination, toUpper: false);
return source.Length;
@@ -212,6 +263,7 @@ namespace System
/// <param name="culture">An object that supplies culture-specific casing rules.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
/// <exception cref="System.ArgumentNullException">
/// Thrown when <paramref name="culture"/> is null.
/// </exception>
@@ -225,7 +277,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- culture.TextInfo.ToUpperAsciiInvariant(source, destination);
+ TextInfo.ToUpperAsciiInvariant(source, destination);
else
culture.TextInfo.ChangeCase(source, destination, toUpper: true);
return source.Length;
@@ -239,6 +291,7 @@ namespace System
/// <param name="destination">The destination span which contains the transformed characters.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination)
{
// Assuming that changing case does not affect length
@@ -246,7 +299,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- CultureInfo.InvariantCulture.TextInfo.ToUpperAsciiInvariant(source, destination);
+ TextInfo.ToUpperAsciiInvariant(source, destination);
else
CultureInfo.InvariantCulture.TextInfo.ChangeCase(source, destination, toUpper: true);
return source.Length;
@@ -260,35 +313,29 @@ namespace System
/// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
public static bool EndsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
+ string.CheckStringComparison(comparisonType);
+
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
return true;
}
- switch (comparisonType)
+ if (comparisonType >= StringComparison.Ordinal || GlobalizationMode.Invariant)
{
- case StringComparison.CurrentCulture:
- return SpanHelpers.EndsWithCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.CurrentCultureIgnoreCase:
- return SpanHelpers.EndsWithCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.InvariantCulture:
- return SpanHelpers.EndsWithCultureHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return SpanHelpers.EndsWithCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.Ordinal:
- return span.EndsWith(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487
+ if (string.GetCaseCompareOfComparisonCulture(comparisonType) == CompareOptions.None)
+ return span.EndsWith(value);
- case StringComparison.OrdinalIgnoreCase:
- return SpanHelpers.EndsWithOrdinalIgnoreCaseHelper(span, value);
+ return (span.Length >= value.Length) ? (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0) : false;
+ }
- default:
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ if (span.Length == 0)
+ {
+ return false;
}
+
+ return (comparisonType >= StringComparison.InvariantCulture) ?
+ CompareInfo.Invariant.IsSuffix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)) :
+ CultureInfo.CurrentCulture.CompareInfo.IsSuffix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
}
/// <summary>
@@ -299,86 +346,35 @@ namespace System
/// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
+ string.CheckStringComparison(comparisonType);
+
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
return true;
}
- switch (comparisonType)
+ if (comparisonType >= StringComparison.Ordinal || GlobalizationMode.Invariant)
{
- case StringComparison.CurrentCulture:
- return SpanHelpers.StartsWithCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.CurrentCultureIgnoreCase:
- return SpanHelpers.StartsWithCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.InvariantCulture:
- return SpanHelpers.StartsWithCultureHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return SpanHelpers.StartsWithCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.Ordinal:
- return span.StartsWith(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487
+ if (string.GetCaseCompareOfComparisonCulture(comparisonType) == CompareOptions.None)
+ return span.StartsWith(value);
- case StringComparison.OrdinalIgnoreCase:
- return SpanHelpers.StartsWithOrdinalIgnoreCaseHelper(span, value);
-
- default:
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ return (span.Length >= value.Length) ? (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(0, value.Length), value) == 0) : false;
}
- }
-
- /// <summary>
- /// Casts a Span of one primitive type <typeparamref name="T"/> to Span of bytes.
- /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
- /// </summary>
- /// <param name="source">The source slice, of type <typeparamref name="T"/>.</param>
- /// <exception cref="System.ArgumentException">
- /// Thrown when <typeparamref name="T"/> contains pointers.
- /// </exception>
- /// <exception cref="System.OverflowException">
- /// Thrown if the Length property of the new Span would exceed Int32.MaxValue.
- /// </exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span<byte> AsBytes<T>(this Span<T> source)
- where T : struct
- {
- if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
- ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
-
- return new Span<byte>(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(source)),
- checked(source.Length * Unsafe.SizeOf<T>()));
- }
- /// <summary>
- /// Casts a ReadOnlySpan of one primitive type <typeparamref name="T"/> to ReadOnlySpan of bytes.
- /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
- /// </summary>
- /// <param name="source">The source slice, of type <typeparamref name="T"/>.</param>
- /// <exception cref="System.ArgumentException">
- /// Thrown when <typeparamref name="T"/> contains pointers.
- /// </exception>
- /// <exception cref="System.OverflowException">
- /// Thrown if the Length property of the new Span would exceed Int32.MaxValue.
- /// </exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<byte> AsBytes<T>(this ReadOnlySpan<T> source)
- where T : struct
- {
- if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
- ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ if (span.Length == 0)
+ {
+ return false;
+ }
- return new ReadOnlySpan<byte>(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(source)),
- checked(source.Length * Unsafe.SizeOf<T>()));
+ return (comparisonType >= StringComparison.InvariantCulture) ?
+ CompareInfo.Invariant.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)) :
+ CultureInfo.CurrentCulture.CompareInfo.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
}
/// <summary>
/// Creates a new span over the portion of the target array.
/// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this T[] array, int start)
{
if (array == null)
@@ -400,6 +396,7 @@ namespace System
/// </summary>
/// <param name="text">The target string.</param>
/// <remarks>Returns default when <paramref name="text"/> is null.</remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> AsSpan(this string text)
{
if (text == null)
@@ -417,6 +414,7 @@ namespace System
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;text.Length).
/// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> AsSpan(this string text, int start)
{
if (text == null)
@@ -442,6 +440,7 @@ namespace System
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> index or <paramref name="length"/> is not in range.
/// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> AsSpan(this string text, int start, int length)
{
if (text == null)
diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs
index effdecf92..f0937c448 100644
--- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs
+++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs
@@ -6,9 +6,13 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
+
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif // BIT64
namespace System
{
@@ -58,7 +62,6 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the character is removed.</param>
/// <param name="trimChar">The specified character to look for and remove.</param>
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, char trimChar)
{
return span.TrimStart(trimChar).TrimEnd(trimChar);
@@ -69,7 +72,6 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the character is removed.</param>
/// <param name="trimChar">The specified character to look for and remove.</param>
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, char trimChar)
{
int start = 0;
@@ -103,6 +105,7 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the characters are removed.</param>
/// <param name="trimChars">The span which contains the set of characters to remove.</param>
+ /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
{
return span.TrimStart(trimChars).TrimEnd(trimChars);
@@ -114,8 +117,14 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the characters are removed.</param>
/// <param name="trimChars">The span which contains the set of characters to remove.</param>
+ /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
{
+ if (trimChars.IsEmpty)
+ {
+ return span.TrimStart();
+ }
+
int start = 0;
for (; start < span.Length; start++)
{
@@ -137,8 +146,14 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the characters are removed.</param>
/// <param name="trimChars">The span which contains the set of characters to remove.</param>
+ /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
{
+ if (trimChars.IsEmpty)
+ {
+ return span.TrimEnd();
+ }
+
int end = span.Length - 1;
for (; end >= 0; end--)
{
@@ -168,6 +183,56 @@ namespace System
}
/// <summary>
+ /// Searches for the specified value and returns true if found. If not found, returns false. Values are compared using IEquatable{T}.Equals(T).
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value to search for.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains<T>(this Span<T> span, T value)
+ where T : IEquatable<T>
+ {
+ if (typeof(T) == typeof(byte))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, byte>(ref value),
+ span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length);
+ }
+
+ /// <summary>
+ /// Searches for the specified value and returns true if found. If not found, returns false. Values are compared using IEquatable{T}.Equals(T).
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value to search for.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains<T>(this ReadOnlySpan<T> span, T value)
+ where T : IEquatable<T>
+ {
+ if (typeof(T) == typeof(byte))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, byte>(ref value),
+ span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length);
+ }
+
+ /// <summary>
/// Searches for the specified value and returns the index of its first occurrence. If not found, returns -1. Values are compared using IEquatable{T}.Equals(T).
/// </summary>
/// <param name="span">The span to search.</param>
@@ -181,7 +246,14 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.IndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
}
/// <summary>
@@ -199,7 +271,8 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
/// <summary>
@@ -216,6 +289,13 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.LastIndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
}
@@ -234,6 +314,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
@@ -241,50 +322,42 @@ namespace System
/// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool SequenceEqual<T>(this Span<T> first, ReadOnlySpan<T> second)
+ public static bool SequenceEqual<T>(this Span<T> span, ReadOnlySpan<T> other)
where T : IEquatable<T>
{
- int length = first.Length;
- if (typeof(T) == typeof(byte))
- return length == second.Length &&
+ int length = span.Length;
+
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ return length == other.Length &&
SpanHelpers.SequenceEqual(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- length);
- return length == second.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(first), ref MemoryMarshal.GetReference(second), length);
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ ((nuint)length) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
+ return length == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
}
/// <summary>
/// Determines the relative order of the sequences being compared by comparing the elements using IComparable{T}.CompareTo(T).
/// </summary>
- public static int SequenceCompareTo<T>(this Span<T> first, ReadOnlySpan<T> second)
+ public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other)
where T : IComparable<T>
{
if (typeof(T) == typeof(byte))
return SpanHelpers.SequenceCompareTo(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- first.Length,
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- second.Length);
- return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(first), first.Length, ref MemoryMarshal.GetReference(second), second.Length);
- }
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
- /// <summary>
- /// Reverses the sequence of the elements in the entire span.
- /// </summary>
- public static void Reverse<T>(this Span<T> span)
- {
- ref T p = ref MemoryMarshal.GetReference(span);
- int i = 0;
- int j = span.Length - 1;
- while (i < j)
- {
- T temp = Unsafe.Add(ref p, i);
- Unsafe.Add(ref p, i) = Unsafe.Add(ref p, j);
- Unsafe.Add(ref p, j) = temp;
- i++;
- j--;
- }
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.SequenceCompareTo(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
+
+ return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length);
}
/// <summary>
@@ -301,7 +374,14 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.IndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
}
/// <summary>
@@ -319,7 +399,8 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
/// <summary>
@@ -336,6 +417,13 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.LastIndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
}
@@ -354,6 +442,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
@@ -495,6 +584,7 @@ namespace System
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
}
@@ -516,6 +606,7 @@ namespace System
Unsafe.As<T, byte>(ref value1),
Unsafe.As<T, byte>(ref value2),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
}
@@ -534,6 +625,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)),
values.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
}
@@ -553,6 +645,7 @@ namespace System
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
}
@@ -574,6 +667,7 @@ namespace System
Unsafe.As<T, byte>(ref value1),
Unsafe.As<T, byte>(ref value2),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
}
@@ -592,6 +686,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)),
values.Length);
+
return SpanHelpers.LastIndexOfAny<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
}
@@ -599,33 +694,42 @@ namespace System
/// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool SequenceEqual<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second)
+ public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
where T : IEquatable<T>
{
- int length = first.Length;
- if (typeof(T) == typeof(byte))
- return length == second.Length &&
+ int length = span.Length;
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ return length == other.Length &&
SpanHelpers.SequenceEqual(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- length);
- return length == second.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(first), ref MemoryMarshal.GetReference(second), length);
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ ((nuint)length) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
+ return length == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
}
/// <summary>
/// Determines the relative order of the sequences being compared by comparing the elements using IComparable{T}.CompareTo(T).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SequenceCompareTo<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second)
+ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
where T : IComparable<T>
{
if (typeof(T) == typeof(byte))
return SpanHelpers.SequenceCompareTo(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- first.Length,
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- second.Length);
- return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(first), first.Length, ref MemoryMarshal.GetReference(second), second.Length);
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.SequenceCompareTo(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
+
+ return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length);
}
/// <summary>
@@ -636,12 +740,13 @@ namespace System
where T : IEquatable<T>
{
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= span.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
}
@@ -653,12 +758,13 @@ namespace System
where T : IEquatable<T>
{
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= span.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
}
@@ -671,12 +777,13 @@ namespace System
{
int spanLength = span.Length;
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength),
@@ -693,12 +800,13 @@ namespace System
{
int spanLength = span.Length;
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength),
@@ -707,7 +815,29 @@ namespace System
}
/// <summary>
- /// Creates a new span over the portion of the target array.
+ /// Reverses the sequence of the elements in the entire span.
+ /// </summary>
+ public static void Reverse<T>(this Span<T> span)
+ {
+ if (span.Length <= 1)
+ {
+ return;
+ }
+
+ ref T first = ref MemoryMarshal.GetReference(span);
+ ref T last = ref Unsafe.Add(ref Unsafe.Add(ref first, span.Length), -1);
+ do
+ {
+ T temp = first;
+ first = last;
+ last = temp;
+ first = ref Unsafe.Add(ref first, 1);
+ last = ref Unsafe.Add(ref last, -1);
+ } while (Unsafe.IsAddressLessThan(ref first, ref last));
+ }
+
+ /// <summary>
+ /// Creates a new span over the target array.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this T[] array)
@@ -716,62 +846,168 @@ namespace System
}
/// <summary>
- /// Creates a new span over the portion of the target array segment.
+ /// Creates a new Span over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the Span.</param>
+ /// <param name="length">The number of items in the Span.</param>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span<T> AsSpan<T>(this ArraySegment<T> arraySegment)
+ public static Span<T> AsSpan<T>(this T[] array, int start, int length)
{
- return new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ return new Span<T>(array, start, length);
}
/// <summary>
- /// Creates a new readonly span over the entire target array.
+ /// Creates a new span over the portion of the target array segment.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<T> AsReadOnlySpan<T>(this T[] array)
+ public static Span<T> AsSpan<T>(this ArraySegment<T> segment)
{
- return new ReadOnlySpan<T>(array);
+ return new Span<T>(segment.Array, segment.Offset, segment.Count);
}
/// <summary>
- /// Creates a new readonly span over the entire target span.
+ /// Creates a new Span over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
- public static ReadOnlySpan<T> AsReadOnlySpan<T>(this Span<T> span) => span;
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the Span.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start)
+ {
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+
+ return new Span<T>(segment.Array, segment.Offset + start, segment.Count - start);
+ }
/// <summary>
- /// Creates a new readonly span over the target array segment.
+ /// Creates a new Span over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the Span.</param>
+ /// <param name="length">The number of items in the Span.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<T> AsReadOnlySpan<T>(this ArraySegment<T> arraySegment)
+ public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start, int length)
{
- return new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+ if (((uint)length) > segment.Count - start)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+
+ return new Span<T>(segment.Array, segment.Offset + start, length);
}
/// <summary>
- /// Creates a new readonly memory over the entire target memory.
+ /// Creates a new memory over the target array.
/// </summary>
- public static ReadOnlyMemory<T> AsReadOnlyMemory<T>(this Memory<T> memory) => memory;
+ public static Memory<T> AsMemory<T>(this T[] array) => new Memory<T>(array);
/// <summary>
- /// Creates a new memory over the portion of the target array.
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=array.Length).
+ /// </exception>
public static Memory<T> AsMemory<T>(this T[] array, int start) => new Memory<T>(array, start);
/// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
+ public static Memory<T> AsMemory<T>(this T[] array, int start, int length) => new Memory<T>(array, start, length);
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array.
+ /// </summary>
+ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment) => new Memory<T>(segment.Array, segment.Offset, segment.Count);
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
+ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start)
+ {
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+
+ return new Memory<T>(segment.Array, segment.Offset + start, segment.Count - start);
+ }
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
+ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start, int length)
+ {
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+ if (((uint)length) > segment.Count - start)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+
+ return new Memory<T>(segment.Array, segment.Offset + start, length);
+ }
+
+ /// <summary>
/// Copies the contents of the array into the span. If the source
/// and destinations overlap, this method behaves as if the original values in
/// a temporary location before the destination is overwritten.
///
- ///<param name="array">The array to copy items from.</param>
+ ///<param name="source">The array to copy items from.</param>
/// <param name="destination">The span to copy items into.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when the destination Span is shorter than the source array.
/// </exception>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void CopyTo<T>(this T[] array, Span<T> destination)
+ public static void CopyTo<T>(this T[] source, Span<T> destination)
{
- new ReadOnlySpan<T>(array).CopyTo(destination);
+ new ReadOnlySpan<T>(source).CopyTo(destination);
}
/// <summary>
@@ -779,16 +1015,16 @@ namespace System
/// and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.
///
- ///<param name="array">The array to copy items from.</param>
+ ///<param name="source">The array to copy items from.</param>
/// <param name="destination">The memory to copy items into.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when the destination is shorter than the source array.
/// </exception>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void CopyTo<T>(this T[] array, Memory<T> destination)
+ public static void CopyTo<T>(this T[] source, Memory<T> destination)
{
- array.CopyTo(destination.Span);
+ source.CopyTo(destination.Span);
}
//
@@ -923,65 +1159,65 @@ namespace System
/// Determines whether two sequences overlap in memory.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Overlaps<T>(this Span<T> first, ReadOnlySpan<T> second)
+ public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other)
{
- return Overlaps((ReadOnlySpan<T>)first, second);
+ return Overlaps((ReadOnlySpan<T>)span, other);
}
/// <summary>
/// Determines whether two sequences overlap in memory and outputs the element offset.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Overlaps<T>(this Span<T> first, ReadOnlySpan<T> second, out int elementOffset)
+ public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other, out int elementOffset)
{
- return Overlaps((ReadOnlySpan<T>)first, second, out elementOffset);
+ return Overlaps((ReadOnlySpan<T>)span, other, out elementOffset);
}
/// <summary>
/// Determines whether two sequences overlap in memory.
/// </summary>
- public static bool Overlaps<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second)
+ public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
{
- if (first.IsEmpty || second.IsEmpty)
+ if (span.IsEmpty || other.IsEmpty)
{
return false;
}
IntPtr byteOffset = Unsafe.ByteOffset(
- ref MemoryMarshal.GetReference(first),
- ref MemoryMarshal.GetReference(second));
+ ref MemoryMarshal.GetReference(span),
+ ref MemoryMarshal.GetReference(other));
if (Unsafe.SizeOf<IntPtr>() == sizeof(int))
{
- return (uint)byteOffset < (uint)(first.Length * Unsafe.SizeOf<T>()) ||
- (uint)byteOffset > (uint)-(second.Length * Unsafe.SizeOf<T>());
+ return (uint)byteOffset < (uint)(span.Length * Unsafe.SizeOf<T>()) ||
+ (uint)byteOffset > (uint)-(other.Length * Unsafe.SizeOf<T>());
}
else
{
- return (ulong)byteOffset < (ulong)((long)first.Length * Unsafe.SizeOf<T>()) ||
- (ulong)byteOffset > (ulong)-((long)second.Length * Unsafe.SizeOf<T>());
+ return (ulong)byteOffset < (ulong)((long)span.Length * Unsafe.SizeOf<T>()) ||
+ (ulong)byteOffset > (ulong)-((long)other.Length * Unsafe.SizeOf<T>());
}
}
/// <summary>
/// Determines whether two sequences overlap in memory and outputs the element offset.
/// </summary>
- public static bool Overlaps<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second, out int elementOffset)
+ public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other, out int elementOffset)
{
- if (first.IsEmpty || second.IsEmpty)
+ if (span.IsEmpty || other.IsEmpty)
{
elementOffset = 0;
return false;
}
IntPtr byteOffset = Unsafe.ByteOffset(
- ref MemoryMarshal.GetReference(first),
- ref MemoryMarshal.GetReference(second));
+ ref MemoryMarshal.GetReference(span),
+ ref MemoryMarshal.GetReference(other));
if (Unsafe.SizeOf<IntPtr>() == sizeof(int))
{
- if ((uint)byteOffset < (uint)(first.Length * Unsafe.SizeOf<T>()) ||
- (uint)byteOffset > (uint)-(second.Length * Unsafe.SizeOf<T>()))
+ if ((uint)byteOffset < (uint)(span.Length * Unsafe.SizeOf<T>()) ||
+ (uint)byteOffset > (uint)-(other.Length * Unsafe.SizeOf<T>()))
{
if ((int)byteOffset % Unsafe.SizeOf<T>() != 0)
ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch();
@@ -997,8 +1233,8 @@ namespace System
}
else
{
- if ((ulong)byteOffset < (ulong)((long)first.Length * Unsafe.SizeOf<T>()) ||
- (ulong)byteOffset > (ulong)-((long)second.Length * Unsafe.SizeOf<T>()))
+ if ((ulong)byteOffset < (ulong)((long)span.Length * Unsafe.SizeOf<T>()) ||
+ (ulong)byteOffset > (ulong)-((long)other.Length * Unsafe.SizeOf<T>()))
{
if ((long)byteOffset % Unsafe.SizeOf<T>() != 0)
ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch();
@@ -1028,7 +1264,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="Span{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T>(
@@ -1052,7 +1288,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="Span{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T, TComparable>(
@@ -1102,7 +1338,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="ReadOnlySpan{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T>(
@@ -1126,7 +1362,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="ReadOnlySpan{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T, TComparable>(
@@ -1166,5 +1402,36 @@ namespace System
value, comparer);
return BinarySearch(span, comparable);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool IsTypeComparableAsBytes<T>(out nuint size)
+ {
+ if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
+ {
+ size = sizeof(byte);
+ return true;
+ }
+
+ if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort))
+ {
+ size = sizeof(char);
+ return true;
+ }
+
+ if (typeof(T) == typeof(int) || typeof(T) == typeof(uint))
+ {
+ size = sizeof(int);
+ return true;
+ }
+
+ if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong))
+ {
+ size = sizeof(long);
+ return true;
+ }
+
+ size = default;
+ return false;
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/MethodAccessException.cs b/src/System.Private.CoreLib/shared/System/MethodAccessException.cs
index 1ca0297b9..f329334b2 100644
--- a/src/System.Private.CoreLib/shared/System/MethodAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/MethodAccessException.cs
@@ -23,13 +23,13 @@ namespace System
HResult = HResults.COR_E_METHODACCESS;
}
- public MethodAccessException(String message)
+ public MethodAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_METHODACCESS;
}
- public MethodAccessException(String message, Exception inner)
+ public MethodAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_METHODACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/MissingFieldException.cs b/src/System.Private.CoreLib/shared/System/MissingFieldException.cs
new file mode 100644
index 000000000..51078acbc
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/MissingFieldException.cs
@@ -0,0 +1,60 @@
+// 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.Runtime.Serialization;
+
+namespace System
+{
+ [Serializable]
+#if !MONO
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public class MissingFieldException : MissingMemberException, ISerializable
+ {
+ public MissingFieldException()
+ : base(SR.Arg_MissingFieldException)
+ {
+ HResult = HResults.COR_E_MISSINGFIELD;
+ }
+
+ public MissingFieldException(string message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_MISSINGFIELD;
+ }
+
+ public MissingFieldException(string message, Exception inner)
+ : base(message, inner)
+ {
+ HResult = HResults.COR_E_MISSINGFIELD;
+ }
+
+ public MissingFieldException(string className, string fieldName)
+ {
+ ClassName = className;
+ MemberName = fieldName;
+ }
+
+ protected MissingFieldException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+
+ public override string Message
+ {
+ get
+ {
+ if (ClassName == null)
+ {
+ return base.Message;
+ }
+ else
+ {
+ // do any desired fixups to classname here.
+ return SR.Format(SR.MissingField_Name, (Signature != null ? FormatSignature(Signature) + " " : "") + ClassName + "." + MemberName);
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/MissingMemberException.cs b/src/System.Private.CoreLib/shared/System/MissingMemberException.cs
new file mode 100644
index 000000000..7aaa38d31
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/MissingMemberException.cs
@@ -0,0 +1,78 @@
+// 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.Runtime.Serialization;
+
+namespace System
+{
+ [Serializable]
+#if !MONO
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public partial class MissingMemberException : MemberAccessException
+ {
+ public MissingMemberException()
+ : base(SR.Arg_MissingMemberException)
+ {
+ HResult = HResults.COR_E_MISSINGMEMBER;
+ }
+
+ public MissingMemberException(string message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_MISSINGMEMBER;
+ }
+
+ public MissingMemberException(string message, Exception inner)
+ : base(message, inner)
+ {
+ HResult = HResults.COR_E_MISSINGMEMBER;
+ }
+
+ public MissingMemberException(string className, string memberName)
+ {
+ ClassName = className;
+ MemberName = memberName;
+ }
+
+ protected MissingMemberException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ ClassName = info.GetString("MMClassName");
+ MemberName = info.GetString("MMMemberName");
+ Signature = (byte[])info.GetValue("MMSignature", typeof(byte[]));
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("MMClassName", ClassName, typeof(string));
+ info.AddValue("MMMemberName", MemberName, typeof(string));
+ info.AddValue("MMSignature", Signature, typeof(byte[]));
+ }
+
+ public override string Message
+ {
+ get
+ {
+ if (ClassName == null)
+ {
+ return base.Message;
+ }
+ else
+ {
+ // do any desired fixups to classname here.
+ return SR.Format(SR.MissingMember_Name, ClassName + "." + MemberName + (Signature != null ? " " + FormatSignature(Signature) : string.Empty));
+ }
+ }
+ }
+
+ // If ClassName != null, GetMessage will construct on the fly using it
+ // and the other variables. This allows customization of the
+ // format depending on the language environment.
+ protected string ClassName;
+ protected string MemberName;
+ protected byte[] Signature;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs b/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs
index cc6c77023..cb07ac7d0 100644
--- a/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs
+++ b/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs
@@ -21,13 +21,13 @@ namespace System
HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
- public MulticastNotSupportedException(String message)
+ public MulticastNotSupportedException(string message)
: base(message)
{
HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
- public MulticastNotSupportedException(String message, Exception inner)
+ public MulticastNotSupportedException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
diff --git a/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs b/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs
index b9c9af06d..9afc10458 100644
--- a/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs
+++ b/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs
@@ -55,13 +55,13 @@ namespace System
protected NotFiniteNumberException(SerializationInfo info, StreamingContext context) : base(info, context)
{
- _offendingNumber = info.GetInt32("OffendingNumber");
+ _offendingNumber = info.GetDouble("OffendingNumber"); // Do not rename (binary serialization)
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
- info.AddValue("OffendingNumber", _offendingNumber, typeof(int));
+ info.AddValue("OffendingNumber", _offendingNumber, typeof(double)); // Do not rename (binary serialization)
}
public double OffendingNumber
diff --git a/src/System.Private.CoreLib/shared/System/NotImplementedException.cs b/src/System.Private.CoreLib/shared/System/NotImplementedException.cs
index 1a3b6afcd..e5f378fed 100644
--- a/src/System.Private.CoreLib/shared/System/NotImplementedException.cs
+++ b/src/System.Private.CoreLib/shared/System/NotImplementedException.cs
@@ -25,12 +25,12 @@ namespace System
{
HResult = HResults.E_NOTIMPL;
}
- public NotImplementedException(String message)
+ public NotImplementedException(string message)
: base(message)
{
HResult = HResults.E_NOTIMPL;
}
- public NotImplementedException(String message, Exception inner)
+ public NotImplementedException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.E_NOTIMPL;
diff --git a/src/System.Private.CoreLib/shared/System/NotSupportedException.cs b/src/System.Private.CoreLib/shared/System/NotSupportedException.cs
index 3180bc283..e3191ea13 100644
--- a/src/System.Private.CoreLib/shared/System/NotSupportedException.cs
+++ b/src/System.Private.CoreLib/shared/System/NotSupportedException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_NOTSUPPORTED;
}
- public NotSupportedException(String message)
+ public NotSupportedException(string message)
: base(message)
{
HResult = HResults.COR_E_NOTSUPPORTED;
}
- public NotSupportedException(String message, Exception innerException)
+ public NotSupportedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_NOTSUPPORTED;
diff --git a/src/System.Private.CoreLib/shared/System/NullReferenceException.cs b/src/System.Private.CoreLib/shared/System/NullReferenceException.cs
index c2e722470..cfbc0fb78 100644
--- a/src/System.Private.CoreLib/shared/System/NullReferenceException.cs
+++ b/src/System.Private.CoreLib/shared/System/NullReferenceException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_NULLREFERENCE;
}
- public NullReferenceException(String message)
+ public NullReferenceException(string message)
: base(message)
{
HResult = HResults.COR_E_NULLREFERENCE;
}
- public NullReferenceException(String message, Exception innerException)
+ public NullReferenceException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_NULLREFERENCE;
diff --git a/src/System.Private.CoreLib/shared/System/Nullable.cs b/src/System.Private.CoreLib/shared/System/Nullable.cs
index 73ad6056c..3c1cbd510 100644
--- a/src/System.Private.CoreLib/shared/System/Nullable.cs
+++ b/src/System.Private.CoreLib/shared/System/Nullable.cs
@@ -141,7 +141,7 @@ namespace System
{
// instantiated generic type only
Type genericType = nullableType.GetGenericTypeDefinition();
- if (Object.ReferenceEquals(genericType, typeof(Nullable<>)))
+ if (object.ReferenceEquals(genericType, typeof(Nullable<>)))
{
return nullableType.GetGenericArguments()[0];
}
diff --git a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs
index 24d5db1da..3d3c15bf7 100644
--- a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs
+++ b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs
@@ -2,6 +2,7 @@
// 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.Buffers.Text;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
@@ -246,12 +247,12 @@ namespace System
private const int DoublePrecision = 15;
private const int ScaleNAN = unchecked((int)0x80000000);
private const int ScaleINF = 0x7FFFFFFF;
- private const int MaxUInt32HexDigits = 8;
private const int MaxUInt32DecDigits = 10;
- private const int MaxUInt64DecDigits = 20;
private const int CharStackBufferSize = 32;
private const string PosNumberFormat = "#";
+ private static readonly string[] s_singleDigitStringCache = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
private static readonly string[] s_posCurrencyFormats =
{
"$#", "#$", "$ #", "# $"
@@ -289,7 +290,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
NumberBuffer number = default;
- DecimalToNumber(value, ref number);
+ DecimalToNumber(ref value, ref number);
ValueStringBuilder sb;
unsafe
@@ -300,7 +301,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, isDecimal:true);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -315,7 +316,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
NumberBuffer number = default;
- DecimalToNumber(value, ref number);
+ DecimalToNumber(ref value, ref number);
ValueStringBuilder sb;
unsafe
@@ -326,7 +327,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, isDecimal: true);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -336,13 +337,12 @@ namespace System
return sb.TryCopyTo(destination, out charsWritten);
}
- private static unsafe void DecimalToNumber(decimal value, ref NumberBuffer number)
+ private static unsafe void DecimalToNumber(ref decimal d, ref NumberBuffer number)
{
- decimal d = value;
-
char* buffer = number.digits;
number.precision = DecimalPrecision;
number.sign = d.IsNegative;
+ number.kind = NumberBufferKind.Decimal;
char* p = buffer + DecimalPrecision;
while ((d.Mid | d.High) != 0)
@@ -351,7 +351,7 @@ namespace System
}
p = UInt32ToDecChars(p, d.Low, 0);
- int i = (int)(buffer + DecimalPrecision - p);
+ int i = (int)((byte*)(buffer + DecimalPrecision) - (byte*)p) >> 1;
number.scale = i - d.Scale;
char* dst = number.digits;
@@ -389,6 +389,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = DoublePrecision;
NumberBuffer number = default;
+ number.kind = NumberBufferKind.Double;
switch (fmt)
{
@@ -410,12 +411,12 @@ namespace System
if (NumberToDouble(ref number) == value)
{
- NumberToString(ref sb, ref number, 'G', DoublePrecision, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', DoublePrecision, info);
}
else
{
DoubleToNumber(value, 17, ref number);
- NumberToString(ref sb, ref number, 'G', 17, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', 17, info);
}
return null;
@@ -452,7 +453,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, isDecimal: false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -489,6 +490,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = FloatPrecision;
NumberBuffer number = default;
+ number.kind = NumberBufferKind.Double;
switch (fmt)
{
@@ -510,12 +512,12 @@ namespace System
if ((float)NumberToDouble(ref number) == value)
{
- NumberToString(ref sb, ref number, 'G', FloatPrecision, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', FloatPrecision, info);
}
else
{
DoubleToNumber(value, 9, ref number);
- NumberToString(ref sb, ref number, 'G', 9, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', 9, info);
}
return null;
}
@@ -551,7 +553,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -583,14 +585,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
UInt32ToDecStr((uint)value, digits) :
- NegativeInt32ToDecStr(value, digits, info.NegativeSign);
+ NegativeInt32ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign);
}
else if (fmtUpper == 'X')
{
@@ -600,6 +600,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -610,7 +611,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -629,14 +630,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
TryUInt32ToDecStr((uint)value, digits, destination, out charsWritten) :
- TryNegativeInt32ToDecStr(value, digits, info.NegativeSign, destination, out charsWritten);
+ TryNegativeInt32ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign, destination, out charsWritten);
}
else if (fmtUpper == 'X')
{
@@ -646,6 +645,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -656,7 +656,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -675,8 +675,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -690,6 +688,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -700,7 +699,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -719,8 +718,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -734,6 +731,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -744,7 +742,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -763,14 +761,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
UInt64ToDecStr((ulong)value, digits) :
- NegativeInt64ToDecStr(value, digits, info.NegativeSign);
+ NegativeInt64ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign);
}
else if (fmtUpper == 'X')
{
@@ -781,6 +777,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -791,7 +788,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -810,14 +807,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
TryUInt64ToDecStr((ulong)value, digits, destination, out charsWritten) :
- TryNegativeInt64ToDecStr(value, digits, info.NegativeSign, destination, out charsWritten);
+ TryNegativeInt64ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign, destination, out charsWritten);
}
else if (fmtUpper == 'X')
{
@@ -828,6 +823,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -838,7 +834,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -857,8 +853,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -873,6 +867,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -883,7 +878,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -902,8 +897,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -918,6 +911,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -928,7 +922,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -958,6 +952,7 @@ namespace System
int i = (int)(buffer + Int32Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -972,18 +967,20 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
- for (int i = sNegative.Length - 1; i >= 0; i--)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits((uint)(-value))) + sNegative.Length;
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
{
- *(--p) = sNegative[i];
- }
+ char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
- Debug.Assert(buffer + bufferLength - p >= 0 && buffer <= p);
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
+ }
+ return result;
}
private static unsafe bool TryNegativeInt32ToDecStr(int value, int digits, string sNegative, Span<char> destination, out int charsWritten)
@@ -993,18 +990,26 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
- for (int i = sNegative.Length - 1; i >= 0; i--)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits((uint)(-value))) + sNegative.Length;
+ if (bufferLength > destination.Length)
{
- *(--p) = sNegative[i];
+ charsWritten = 0;
+ return false;
}
- Debug.Assert(buffer + bufferLength - p >= 0 && buffer <= p);
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
+ {
+ char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
+
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
private static unsafe string Int32ToHexStr(int value, char hexBase, int digits)
@@ -1012,11 +1017,14 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits);
- char* buffer = stackalloc char[bufferLength];
-
- char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((uint)value));
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
+ {
+ char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
+ Debug.Assert(p == buffer);
+ }
+ return result;
}
private static unsafe bool TryInt32ToHexStr(int value, char hexBase, int digits, Span<char> destination, out int charsWritten)
@@ -1024,11 +1032,20 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits);
- char* buffer = stackalloc char[bufferLength];
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((uint)value));
+ if (bufferLength > destination.Length)
+ {
+ charsWritten = 0;
+ return false;
+ }
- char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
+ {
+ char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
private static unsafe char* Int32ToHexChars(char* buffer, uint value, int hexBase, int digits)
@@ -1052,6 +1069,7 @@ namespace System
char* p = UInt32ToDecChars(buffer + UInt32Precision, value, 0);
int i = (int)(buffer + UInt32Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -1073,56 +1091,69 @@ namespace System
private static unsafe string UInt32ToDecStr(uint value, int digits)
{
- if (digits <= 1)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+
+ // For single-digit values that are very common, especially 0 and 1, just return cached strings.
+ if (bufferLength == 1)
{
- char* buffer = stackalloc char[MaxUInt32DecDigits];
+ return s_singleDigitStringCache[value];
+ }
- char* start = buffer + MaxUInt32DecDigits;
- char* p = start;
- do
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
+ {
+ char* p = buffer + bufferLength;
+ if (digits <= 1)
{
- // TODO https://github.com/dotnet/coreclr/issues/3439
- uint div = value / 10;
- *(--p) = (char)('0' + value - (div * 10));
- value = div;
+ do
+ {
+ // TODO https://github.com/dotnet/coreclr/issues/3439
+ uint div = value / 10;
+ *(--p) = (char)('0' + value - (div * 10));
+ value = div;
+ }
+ while (value != 0);
}
- while (value != 0);
-
- return new string(p, 0, (int)(start - p));
- }
- else
- {
- int bufferSize = Math.Max(digits, MaxUInt32DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = UInt32ToDecChars(buffer + bufferSize, value, digits);
- return new string(p, 0, (int)(buffer + bufferSize - p));
+ else
+ {
+ p = UInt32ToDecChars(p, value, digits);
+ }
+ Debug.Assert(p == buffer);
}
+ return result;
}
private static unsafe bool TryUInt32ToDecStr(uint value, int digits, Span<char> destination, out int charsWritten)
{
- if (digits <= 1)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+ if (bufferLength > destination.Length)
{
- char* buffer = stackalloc char[MaxUInt32DecDigits];
- char* start = buffer + MaxUInt32DecDigits;
- char* p = start;
- do
- {
- // TODO https://github.com/dotnet/coreclr/issues/3439
- uint div = value / 10;
- *(--p) = (char)('0' + value - (div * 10));
- value = div;
- }
- while (value != 0);
- return TryCopyTo(p, (int)(start - p), destination, out charsWritten);
+ charsWritten = 0;
+ return false;
}
- else
+
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
{
- int bufferSize = Math.Max(digits, MaxUInt32DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = UInt32ToDecChars(buffer + bufferSize, value, digits);
- return TryCopyTo(p, (int)(buffer + bufferSize - p), destination, out charsWritten);
+ char* p = buffer + bufferLength;
+ if (digits <= 1)
+ {
+ do
+ {
+ // TODO https://github.com/dotnet/coreclr/issues/3439
+ uint div = value / 10;
+ *(--p) = (char)('0' + value - (div * 10));
+ value = div;
+ }
+ while (value != 0);
+ }
+ else
+ {
+ p = UInt32ToDecChars(p, value, digits);
+ }
+ Debug.Assert(p == buffer);
}
+ return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1158,6 +1189,7 @@ namespace System
int i = (int)(buffer + Int64Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -1176,24 +1208,26 @@ namespace System
ulong value = (ulong)(-input);
- int bufferLength = Math.Max(digits, MaxUInt64DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = buffer + bufferLength;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value)) + sNegative.Length;
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
- }
- p = UInt32ToDecChars(p, Low32(value), digits);
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
- for (int i = sNegative.Length - 1; i >= 0; i--)
- {
- *(--p) = sNegative[i];
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
}
-
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ return result;
}
private static unsafe bool TryNegativeInt64ToDecStr(long input, int digits, string sNegative, Span<char> destination, out int charsWritten)
@@ -1207,64 +1241,80 @@ namespace System
ulong value = (ulong)(-input);
- int bufferLength = Math.Max(digits, MaxUInt64DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = buffer + bufferLength;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits((ulong)(-input))) + sNegative.Length;
+ if (bufferLength > destination.Length)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
+ charsWritten = 0;
+ return false;
}
- p = UInt32ToDecChars(p, Low32(value), digits);
- for (int i = sNegative.Length - 1; i >= 0; i--)
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
{
- *(--p) = sNegative[i];
- }
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
private static unsafe string Int64ToHexStr(long value, char hexBase, int digits)
{
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits * 2);
- char* buffer = stackalloc char[bufferLength];
- int index = bufferLength;
-
- char* p;
- if (High32((ulong)value) != 0)
- {
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, 8);
- p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
- }
- else
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong)value));
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
{
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ char* p = buffer + bufferLength;
+ if (High32((ulong)value) != 0)
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, 8);
+ p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
+ }
+ else
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ }
+ Debug.Assert(p == buffer);
}
-
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ return result;
}
private static unsafe bool TryInt64ToHexStr(long value, char hexBase, int digits, Span<char> destination, out int charsWritten)
{
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits * 2);
- char* buffer = stackalloc char[bufferLength];
- int index = bufferLength;
-
- char* p;
- if (High32((ulong)value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong)value));
+ if (bufferLength > destination.Length)
{
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, 8);
- p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
+ charsWritten = 0;
+ return false;
}
- else
+
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
{
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ char* p = buffer + bufferLength;
+ if (High32((ulong)value) != 0)
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, 8);
+ p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
+ }
+ else
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ }
+ Debug.Assert(p == buffer);
}
-
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ return true;
}
private static unsafe void UInt64ToNumber(ulong value, ref NumberBuffer number)
@@ -1281,6 +1331,7 @@ namespace System
int i = (int)(buffer + UInt64Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -1293,17 +1344,27 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferSize = Math.Max(digits, MaxUInt64DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = buffer + bufferSize;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+
+ // For single-digit values that are very common, especially 0 and 1, just return cached strings.
+ if (bufferLength == 1)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
+ return s_singleDigitStringCache[value];
}
- p = UInt32ToDecChars(p, Low32(value), digits);
- return new string(p, 0, (int)(buffer + bufferSize - p));
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
+ {
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer);
+ }
+ return result;
}
private static unsafe bool TryUInt64ToDecStr(ulong value, int digits, Span<char> destination, out int charsWritten)
@@ -1311,17 +1372,26 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferSize = Math.Max(digits, MaxUInt64DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = buffer + bufferSize;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+ if (bufferLength > destination.Length)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
+ charsWritten = 0;
+ return false;
}
- p = UInt32ToDecChars(p, Low32(value), digits);
- return TryCopyTo(p, (int)(buffer + bufferSize - p), destination, out charsWritten);
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
+ {
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
internal static unsafe char ParseFormatSpecifier(ReadOnlySpan<char> format, out int digits)
@@ -1390,22 +1460,21 @@ namespace System
'\0';
}
- internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info, bool isDecimal)
+ internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info)
{
- int nMinDigits = -1;
+ Debug.Assert(number.kind != NumberBufferKind.Unknown);
switch (format)
{
case 'C':
case 'c':
{
- nMinDigits = nMaxDigits >= 0 ? nMaxDigits : info.CurrencyDecimalDigits;
if (nMaxDigits < 0)
nMaxDigits = info.CurrencyDecimalDigits;
RoundNumber(ref number, number.scale + nMaxDigits); // Don't change this line to use digPos since digCount could have its sign changed.
- FormatCurrency(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatCurrency(ref sb, ref number, nMaxDigits, info);
break;
}
@@ -1414,16 +1483,14 @@ namespace System
case 'f':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.NumberDecimalDigits;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.NumberDecimalDigits;
RoundNumber(ref number, number.scale + nMaxDigits);
if (number.sign)
sb.Append(info.NegativeSign);
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
break;
}
@@ -1432,13 +1499,11 @@ namespace System
case 'n':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.NumberDecimalDigits; // Since we are using digits in our calculation
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.NumberDecimalDigits; // Since we are using digits in our calculation
RoundNumber(ref number, number.scale + nMaxDigits);
- FormatNumber(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatNumber(ref sb, ref number, nMaxDigits, info);
break;
}
@@ -1447,9 +1512,7 @@ namespace System
case 'e':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = 6;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = 6;
nMaxDigits++;
RoundNumber(ref number, nMaxDigits);
@@ -1457,7 +1520,7 @@ namespace System
if (number.sign)
sb.Append(info.NegativeSign);
- FormatScientific(ref sb, ref number, nMinDigits, nMaxDigits, info, format);
+ FormatScientific(ref sb, ref number, nMaxDigits, info, format);
break;
}
@@ -1465,40 +1528,28 @@ namespace System
case 'G':
case 'g':
{
- bool enableRounding = true;
+ bool noRounding = false;
if (nMaxDigits < 1)
{
- if (isDecimal && (nMaxDigits == -1))
+ if ((number.kind == NumberBufferKind.Decimal) && (nMaxDigits == -1))
{
- // Default to 29 digits precision only for G formatting without a precision specifier
- // This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = nMinDigits = DecimalPrecision;
- enableRounding = false; // Turn off rounding for ECMA compliance to output trailing 0's after decimal as significant
+ noRounding = true; // Turn off rounding for ECMA compliance to output trailing 0's after decimal as significant
+ goto SkipRounding;
}
else
{
// This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = nMinDigits = number.precision;
+ nMaxDigits = number.precision;
}
}
- else
- nMinDigits = nMaxDigits;
- if (enableRounding) // Don't round for G formatting without precision
- RoundNumber(ref number, nMaxDigits); // This also fixes up the minus zero case
- else
- {
- if (isDecimal && (number.digits[0] == 0))
- {
- // Minus zero should be formatted as 0
- number.sign = false;
- }
- }
+ RoundNumber(ref number, nMaxDigits);
+SkipRounding:
if (number.sign)
sb.Append(info.NegativeSign);
- FormatGeneral(ref sb, ref number, nMinDigits, nMaxDigits, info, (char)(format - ('G' - 'E')), !enableRounding);
+ FormatGeneral(ref sb, ref number, nMaxDigits, info, (char)(format - ('G' - 'E')), noRounding);
break;
}
@@ -1507,14 +1558,12 @@ namespace System
case 'p':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.PercentDecimalDigits;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.PercentDecimalDigits;
number.scale += 2;
RoundNumber(ref number, number.scale + nMaxDigits);
- FormatPercent(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatPercent(ref sb, ref number, nMaxDigits, info);
break;
}
@@ -1526,6 +1575,8 @@ namespace System
internal static unsafe void NumberToStringFormat(ref ValueStringBuilder sb, ref NumberBuffer number, ReadOnlySpan<char> format, NumberFormatInfo info)
{
+ Debug.Assert(number.kind != NumberBufferKind.Unknown);
+
int digitCount;
int decimalPos;
int firstDigit;
@@ -1648,7 +1699,6 @@ namespace System
}
else
{
- number.sign = false; // We need to format -0 without the sign set.
number.scale = 0; // Decimals with scale ('0.00') should be rounded.
}
@@ -1881,7 +1931,7 @@ namespace System
}
}
- private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negCurrencyFormats[info.CurrencyNegativePattern] :
@@ -1892,7 +1942,7 @@ namespace System
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
@@ -1907,7 +1957,7 @@ namespace System
}
}
- private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, int[] groupDigits, string sDecimal, string sGroup)
+ private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, int[] groupDigits, string sDecimal, string sGroup)
{
int digPos = number.scale;
char* dig = number.digits;
@@ -1917,13 +1967,14 @@ namespace System
if (groupDigits != null)
{
int groupSizeIndex = 0; // Index into the groupDigits array.
- int groupSizeCount = groupDigits[groupSizeIndex]; // The current total of group size.
int bufferSize = digPos; // The length of the result buffer string.
int groupSize = 0; // The current group size.
// Find out the size of the string buffer for the result.
if (groupDigits.Length != 0) // You can pass in 0 length arrays
{
+ int groupSizeCount = groupDigits[groupSizeIndex]; // The current total of group size.
+
while (digPos > groupSizeCount)
{
groupSize = groupDigits[groupSizeIndex];
@@ -2008,7 +2059,7 @@ namespace System
}
}
- private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negNumberFormats[info.NumberNegativePattern] :
@@ -2019,7 +2070,7 @@ namespace System
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
@@ -2031,7 +2082,7 @@ namespace System
}
}
- private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, char expChar)
+ private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar)
{
char* dig = number.digits;
@@ -2068,7 +2119,7 @@ namespace System
sb.Append(p, (int)(digits + MaxUInt32DecDigits - p));
}
- private static unsafe void FormatGeneral(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, char expChar, bool bSuppressScientific)
+ private static unsafe void FormatGeneral(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar, bool bSuppressScientific)
{
int digPos = number.scale;
bool scientific = false;
@@ -2115,7 +2166,7 @@ namespace System
FormatExponent(ref sb, info, number.scale - 1, expChar, 2, true);
}
- private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negPercentFormats[info.PercentNegativePattern] :
@@ -2126,7 +2177,7 @@ namespace System
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
@@ -2173,7 +2224,11 @@ namespace System
if (i == 0)
{
number.scale = 0;
- number.sign = false;
+
+ if (number.kind == NumberBufferKind.Integer)
+ {
+ number.sign = false;
+ }
}
dig[i] = '\0';
}
diff --git a/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs b/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs
index 2316f99bd..1730cf18f 100644
--- a/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs
+++ b/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs
@@ -15,17 +15,27 @@ namespace System
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal unsafe ref struct NumberBuffer // needs to match layout of NUMBER in coreclr's src/classlibnative/bcltype/number.h
{
- public int precision;
- public int scale;
- private int _sign;
- private DigitsAndNullTerminator _digits;
- private char* _allDigits;
+ public int precision; // 0
+ public int scale; // 4
+ private int _sign; // 8
+ private NumberBufferKind _kind; // 12
+ private char* _allDigits; // 16
+ private DigitsAndNullTerminator _digits; // 20 or 24
public bool sign { get => _sign != 0; set => _sign = value ? 1 : 0; }
public char* digits => (char*)Unsafe.AsPointer(ref _digits);
+ public NumberBufferKind kind { get => _kind; set => _kind = value; }
[StructLayout(LayoutKind.Sequential, Size = (NumberMaxDigits + 1) * sizeof(char))]
private struct DigitsAndNullTerminator { }
}
+
+ internal enum NumberBufferKind // needs to match NUMBER_KIND in coreclr's src/classlibnative/bcltype/number.h
+ {
+ Unknown = 0,
+ Integer = 1,
+ Decimal = 2,
+ Double = 3
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Number.Parsing.cs b/src/System.Private.CoreLib/shared/System/Number.Parsing.cs
index 46951094e..7c7866a90 100644
--- a/src/System.Private.CoreLib/shared/System/Number.Parsing.cs
+++ b/src/System.Private.CoreLib/shared/System/Number.Parsing.cs
@@ -5,6 +5,11 @@
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
+#if MONO
+using System.Runtime.CompilerServices;
+#else
+using Internal.Runtime.CompilerServices;
+#endif
namespace System
{
@@ -30,129 +35,26 @@ namespace System
private const int Int64Precision = 19;
private const int UInt64Precision = 20;
- private static bool HexNumberToInt32(ref NumberBuffer number, ref int value)
+ /// <summary>256-element map from an ASCII char to its hex value, e.g. arr['b'] == 11. 0xFF means it's not a hex digit.</summary>
+ private static readonly int[] s_charToHexLookup =
{
- uint passedValue = 0;
- bool returnValue = HexNumberToUInt32(ref number, ref passedValue);
- value = (int)passedValue;
- return returnValue;
- }
-
- private static bool HexNumberToInt64(ref NumberBuffer number, ref long value)
- {
- ulong passedValue = 0;
- bool returnValue = HexNumberToUInt64(ref number, ref passedValue);
- value = (long)passedValue;
- return returnValue;
- }
-
- private static unsafe bool HexNumberToUInt32(ref NumberBuffer number, ref uint value)
- {
- int i = number.scale;
- if (i > UInt32Precision || i < number.precision)
- {
- return false;
- }
- char* p = number.digits;
- Debug.Assert(p != null);
-
- uint n = 0;
- while (--i >= 0)
- {
- if (n > ((uint)0xFFFFFFFF / 16))
- {
- return false;
- }
- n *= 16;
- if (*p != '\0')
- {
- uint newN = n;
- if (*p != '\0')
- {
- if (*p >= '0' && *p <= '9')
- {
- newN += (uint)(*p - '0');
- }
- else
- {
- if (*p >= 'A' && *p <= 'F')
- {
- newN += (uint)((*p - 'A') + 10);
- }
- else
- {
- Debug.Assert(*p >= 'a' && *p <= 'f');
- newN += (uint)((*p - 'a') + 10);
- }
- }
- p++;
- }
-
- // Detect an overflow here...
- if (newN < n)
- {
- return false;
- }
- n = newN;
- }
- }
- value = n;
- return true;
- }
-
- private static unsafe bool HexNumberToUInt64(ref NumberBuffer number, ref ulong value)
- {
- int i = number.scale;
- if (i > UInt64Precision || i < number.precision)
- {
- return false;
- }
- char* p = number.digits;
- Debug.Assert(p != null);
-
- ulong n = 0;
- while (--i >= 0)
- {
- if (n > (0xFFFFFFFFFFFFFFFF / 16))
- {
- return false;
- }
- n *= 16;
- if (*p != '\0')
- {
- ulong newN = n;
- if (*p != '\0')
- {
- if (*p >= '0' && *p <= '9')
- {
- newN += (ulong)(*p - '0');
- }
- else
- {
- if (*p >= 'A' && *p <= 'F')
- {
- newN += (ulong)((*p - 'A') + 10);
- }
- else
- {
- Debug.Assert(*p >= 'a' && *p <= 'f');
- newN += (ulong)((*p - 'a') + 10);
- }
- }
- p++;
- }
-
- // Detect an overflow here...
- if (newN < n)
- {
- return false;
- }
- n = newN;
- }
- }
- value = n;
- return true;
- }
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 15
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 31
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 47
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 63
+ 0xFF, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 79
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 95
+ 0xFF, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 111
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 127
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 143
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 159
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 175
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 191
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 207
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 223
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 239
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 255
+ };
private static unsafe bool NumberToInt32(ref NumberBuffer number, ref int value)
{
@@ -173,7 +75,7 @@ namespace System
n *= 10;
if (*p != '\0')
{
- n += (int)(*p++ - '0');
+ n += (*p++ - '0');
}
}
if (number.sign)
@@ -214,7 +116,7 @@ namespace System
n *= 10;
if (*p != '\0')
{
- n += (int)(*p++ - '0');
+ n += (*p++ - '0');
}
}
if (number.sign)
@@ -300,104 +202,147 @@ namespace System
return true;
}
- internal unsafe static int ParseInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
+ internal static int ParseInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
- NumberBuffer number = default;
- int i = 0;
-
- StringToNumber(s, style, ref number, info, false);
-
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToInt32(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseInt32IntegerStyle(value, styles, info, out int intResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int32));
}
+ return intResult;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToInt32(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt32HexNumberStyle(value, styles, info, out uint hexResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int32));
}
+ return (int)hexResult;
}
- return i;
- }
- internal unsafe static long ParseInt64(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
- {
NumberBuffer number = default;
- long i = 0;
-
- StringToNumber(value, options, ref number, numfmt, false);
+ int result = 0;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToInt32(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Int32));
+ }
+ return result;
+ }
- if ((options & NumberStyles.AllowHexSpecifier) != 0)
+ internal static long ParseInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
+ {
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToInt64(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseInt64IntegerStyle(value, styles, info, out long intResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int64));
}
+ return intResult;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToInt64(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt64HexNumberStyle(value, styles, info, out ulong hexResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int64));
}
+ return (long)hexResult;
}
- return i;
- }
- internal unsafe static uint ParseUInt32(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
- {
NumberBuffer number = default;
- uint i = 0;
+ long result = 0;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToInt64(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Int64));
+ }
+ return result;
+ }
- StringToNumber(value, options, ref number, numfmt, false);
+ internal static uint ParseUInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
+ {
+ uint result = 0;
- if ((options & NumberStyles.AllowHexSpecifier) != 0)
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToUInt32(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseUInt32IntegerStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt32));
}
+ return result;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToUInt32(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt32HexNumberStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt32));
}
+ return result;
}
- return i;
+ NumberBuffer number = default;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToUInt32(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_UInt32));
+ }
+ return result;
}
- internal unsafe static ulong ParseUInt64(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ internal static ulong ParseUInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
- NumberBuffer number = default;
- ulong i = 0;
+ ulong result = 0;
- StringToNumber(value, options, ref number, numfmt, false);
- if ((options & NumberStyles.AllowHexSpecifier) != 0)
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToUInt64(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseUInt64IntegerStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt64));
}
+ return result;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToUInt64(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt64HexNumberStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt64));
}
+ return result;
}
- return i;
+
+ NumberBuffer number = default;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToUInt64(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_UInt64));
+ }
+ return result;
}
- private unsafe static bool ParseNumber(ref char* str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo numfmt, bool parseDecimal)
+ private static unsafe bool ParseNumber(ref char* str, char* strEnd, NumberStyles styles, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
+ Debug.Assert(str != null);
+ Debug.Assert(strEnd != null);
+ Debug.Assert(str <= strEnd);
+ Debug.Assert((styles & NumberStyles.AllowHexSpecifier) == 0);
+
const int StateSign = 0x0001;
const int StateParens = 0x0002;
const int StateDigits = 0x0004;
@@ -412,44 +357,44 @@ namespace System
string currSymbol = null; // currency symbol from NumberFormatInfo.
bool parsingCurrency = false;
- if ((options & NumberStyles.AllowCurrencySymbol) != 0)
+ if ((styles & NumberStyles.AllowCurrencySymbol) != 0)
{
- currSymbol = numfmt.CurrencySymbol;
+ currSymbol = info.CurrencySymbol;
// The idea here is to match the currency separators and on failure match the number separators to keep the perf of VB's IsNumeric fast.
// The values of decSep are setup to use the correct relevant separator (currency in the if part and decimal in the else part).
- decSep = numfmt.CurrencyDecimalSeparator;
- groupSep = numfmt.CurrencyGroupSeparator;
+ decSep = info.CurrencyDecimalSeparator;
+ groupSep = info.CurrencyGroupSeparator;
parsingCurrency = true;
}
else
{
- decSep = numfmt.NumberDecimalSeparator;
- groupSep = numfmt.NumberGroupSeparator;
+ decSep = info.NumberDecimalSeparator;
+ groupSep = info.NumberGroupSeparator;
}
int state = 0;
char* p = str;
- char ch = *p;
+ char ch = p < strEnd ? *p : '\0';
char* next;
while (true)
{
// Eat whitespace unless we've found a sign which isn't followed by a currency symbol.
// "-Kr 1231.47" is legal but "- 1231.47" is not.
- if (!IsWhite(ch) || (options & NumberStyles.AllowLeadingWhite) == 0 || ((state & StateSign) != 0 && ((state & StateCurrency) == 0 && numfmt.NumberNegativePattern != 2)))
+ if (!IsWhite(ch) || (styles & NumberStyles.AllowLeadingWhite) == 0 || ((state & StateSign) != 0 && ((state & StateCurrency) == 0 && info.NumberNegativePattern != 2)))
{
- if ((((options & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, numfmt.PositiveSign)) != null || ((next = MatchChars(p, numfmt.NegativeSign)) != null && (number.sign = true))))
+ if ((((styles & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || ((next = MatchChars(p, strEnd, info.NegativeSign)) != null && (number.sign = true))))
{
state |= StateSign;
p = next - 1;
}
- else if (ch == '(' && ((options & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0))
+ else if (ch == '(' && ((styles & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0))
{
state |= StateSign | StateParens;
number.sign = true;
}
- else if (currSymbol != null && (next = MatchChars(p, currSymbol)) != null)
+ else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null)
{
state |= StateCurrency;
currSymbol = null;
@@ -462,13 +407,13 @@ namespace System
break;
}
}
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
int digCount = 0;
int digEnd = 0;
while (true)
{
- if ((ch >= '0' && ch <= '9') || (((options & NumberStyles.AllowHexSpecifier) != 0) && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))))
+ if (IsDigit(ch))
{
state |= StateDigits;
@@ -493,12 +438,12 @@ namespace System
number.scale--;
}
}
- else if (((options & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, numfmt.NumberDecimalSeparator)) != null))
+ else if (((styles & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, strEnd, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, strEnd, info.NumberDecimalSeparator)) != null))
{
state |= StateDecimal;
p = next - 1;
}
- else if (((options & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, numfmt.NumberGroupSeparator)) != null))
+ else if (((styles & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, strEnd, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, strEnd, info.NumberGroupSeparator)) != null))
{
p = next - 1;
}
@@ -506,7 +451,7 @@ namespace System
{
break;
}
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
bool negExp = false;
@@ -514,35 +459,35 @@ namespace System
number.digits[digEnd] = '\0';
if ((state & StateDigits) != 0)
{
- if ((ch == 'E' || ch == 'e') && ((options & NumberStyles.AllowExponent) != 0))
+ if ((ch == 'E' || ch == 'e') && ((styles & NumberStyles.AllowExponent) != 0))
{
char* temp = p;
- ch = *++p;
- if ((next = MatchChars(p, numfmt.positiveSign)) != null)
+ ch = ++p < strEnd ? *p : '\0';
+ if ((next = MatchChars(p, strEnd, info.positiveSign)) != null)
{
- ch = *(p = next);
+ ch = (p = next) < strEnd ? *p : '\0';
}
- else if ((next = MatchChars(p, numfmt.negativeSign)) != null)
+ else if ((next = MatchChars(p, strEnd, info.negativeSign)) != null)
{
- ch = *(p = next);
+ ch = (p = next) < strEnd ? *p : '\0';
negExp = true;
}
- if (ch >= '0' && ch <= '9')
+ if (IsDigit(ch))
{
int exp = 0;
do
{
exp = exp * 10 + (ch - '0');
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
if (exp > 1000)
{
exp = 9999;
- while (ch >= '0' && ch <= '9')
+ while (IsDigit(ch))
{
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
}
- } while (ch >= '0' && ch <= '9');
+ } while (IsDigit(ch));
if (negExp)
{
exp = -exp;
@@ -552,14 +497,14 @@ namespace System
else
{
p = temp;
- ch = *p;
+ ch = p < strEnd ? *p : '\0';
}
}
while (true)
{
- if (!IsWhite(ch) || (options & NumberStyles.AllowTrailingWhite) == 0)
+ if (!IsWhite(ch) || (styles & NumberStyles.AllowTrailingWhite) == 0)
{
- if (((options & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, numfmt.PositiveSign)) != null || (((next = MatchChars(p, numfmt.NegativeSign)) != null) && (number.sign = true))))
+ if (((styles & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || (((next = MatchChars(p, strEnd, info.NegativeSign)) != null) && (number.sign = true))))
{
state |= StateSign;
p = next - 1;
@@ -568,7 +513,7 @@ namespace System
{
state &= ~StateParens;
}
- else if (currSymbol != null && (next = MatchChars(p, currSymbol)) != null)
+ else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null)
{
currSymbol = null;
p = next - 1;
@@ -578,7 +523,7 @@ namespace System
break;
}
}
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
if ((state & StateParens) == 0)
{
@@ -601,206 +546,1109 @@ namespace System
return false;
}
- internal unsafe static bool TryParseInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out int result)
+ internal static bool TryParseInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out int result)
{
- NumberBuffer number = default;
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseInt32IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
result = 0;
- if (!TryStringToNumber(s, style, ref number, info, false))
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- return false;
+ bool overflow = false;
+ return TryParseUInt32HexNumberStyle(value, styles, info, out Unsafe.As<int, uint>(ref result), ref overflow);
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ NumberBuffer number = default;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToInt32(ref number, ref result);
+ }
+
+ /// <summary>Parses int limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseInt32IntegerStyle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out int result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ int sign = 1;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- if (!HexNumberToInt32(ref number, ref result))
+ do
{
- return false;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
}
+ while (IsWhite(num));
}
- else
+
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!NumberToInt32(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '-')
+ {
+ sign = -1;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ sign = -1;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ }
+
+ int answer = 0;
+
+ if (IsDigit(num))
+ {
+ // Skip past leading zeros.
+ if (num == '0')
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 9 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 8; i++) // next 8 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
+ }
+
+ // Potential overflow now processing the 10th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if (answer > int.MaxValue / 10)
+ {
+ overflow = true;
+ }
+ answer = answer * 10 + num - '0';
+ if ((uint)answer > (uint)int.MaxValue + (-1 * sign + 1) / 2)
+ {
+ overflow = true;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length)
+ goto DoneAtEndButPotentialOverflow;
+ num = value[index];
}
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
}
+ result = answer * sign;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static bool TryParseInt64(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out long result)
+ /// <summary>Parses long inputs limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseInt64IntegerStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out long result, ref bool failureIsOverflow)
{
- NumberBuffer number = default;
- result = 0;
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
- if (!TryStringToNumber(s, style, ref number, info, false))
+ bool overflow = false;
+ int sign = 1;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!HexNumberToInt64(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '-')
+ {
+ sign = -1;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ sign = -1;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
}
}
- else
+
+ long answer = 0;
+
+ if (IsDigit(num))
{
- if (!NumberToInt64(ref number, ref result))
+ // Skip past leading zeros.
+ if (num == '0')
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 18 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 17; i++) // next 17 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
+ }
+
+ // Potential overflow now processing the 19th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if (answer > long.MaxValue / 10)
+ {
+ overflow = true;
+ }
+ answer = answer * 10 + num - '0';
+ if ((ulong)answer > (ulong)long.MaxValue + (ulong)((-1 * sign + 1) / 2)) // + sign => 0, - sign => 1
+ {
+ overflow = true;
}
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
}
+ result = answer * sign;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static bool TryParseUInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out uint result)
+ internal static bool TryParseInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out long result)
{
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseInt64IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
+ result = 0;
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
+ {
+ bool overflow = false;
+ return TryParseUInt64HexNumberStyle(value, styles, info, out Unsafe.As<long, ulong>(ref result), ref overflow);
+ }
+
+ NumberBuffer number = default;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToInt64(ref number, ref result);
+ }
+
+ internal static bool TryParseUInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out uint result)
+ {
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseUInt32IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
+ {
+ bool overflow = false;
+ return TryParseUInt32HexNumberStyle(value, styles, info, out result, ref overflow);
+ }
+
NumberBuffer number = default;
result = 0;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToUInt32(ref number, ref result);
+ }
+
+ /// <summary>Parses uint limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseUInt32IntegerStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out uint result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
- if (!TryStringToNumber(s, style, ref number, info, false))
+ bool overflow = false;
+ bool hasNegativeSign = false;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!HexNumberToUInt32(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '-')
+ {
+ hasNegativeSign = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ hasNegativeSign = true;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
}
}
- else
+
+ int answer = 0;
+
+ if (IsDigit(num))
{
- if (!NumberToUInt32(ref number, ref result))
+ // Skip past leading zeros.
+ if (num == '0')
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 9 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 8; i++) // next 8 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
+ }
+
+ // Potential overflow now processing the 10th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if ((uint)answer > uint.MaxValue / 10 || ((uint)answer == uint.MaxValue / 10 && num > '5'))
+ {
+ overflow = true;
}
+ answer = answer * 10 + num - '0';
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
}
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow || (hasNegativeSign && answer != 0))
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ result = (uint)answer;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static bool TryParseUInt64(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out ulong result)
+ /// <summary>Parses uint limited to styles that make up NumberStyles.HexNumber.</summary>
+ private static bool TryParseUInt32HexNumberStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out uint result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ int index = 0;
+ int num = value[0];
+ int numValue = 0;
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
+ }
+
+ int answer = 0;
+ int[] charToHexLookup = s_charToHexLookup;
+
+ if ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ // Skip past leading zeros.
+ if (num == '0')
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ } while (num == '0');
+ if ((uint)num >= (uint)charToHexLookup.Length || charToHexLookup[num] == 0xFF) goto HasTrailingChars;
+ }
+
+ // Parse up through 8 digits, as no overflow is possible
+ answer = charToHexLookup[num]; // first digit
+ index++;
+ for (int i = 0; i < 7; i++) // next 7 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ answer = 16 * answer + numValue;
+ }
+
+ // If there's another digit, it's an overflow.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ overflow = true;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility. Read through any remaining digits.
+ num = value[index];
+ while ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ DoneAtEnd:
+ result = (uint)answer;
+ return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
+ }
+
+ internal static bool TryParseUInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out ulong result)
{
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseUInt64IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
+ {
+ bool overflow = false;
+ return TryParseUInt64HexNumberStyle(value, styles, info, out result, ref overflow);
+ }
+
NumberBuffer number = default;
result = 0;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToUInt64(ref number, ref result);
+ }
- if (!TryStringToNumber(s, style, ref number, info, false))
+ /// <summary>Parses ulong limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseUInt64IntegerStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out ulong result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ bool hasNegativeSign = false;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!HexNumberToUInt64(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '-')
+ {
+ hasNegativeSign = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ hasNegativeSign = true;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
}
}
- else
+
+ long answer = 0;
+
+ if (IsDigit(num))
{
- if (!NumberToUInt64(ref number, ref result))
+ // Skip past leading zeros.
+ if (num == '0')
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 19 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 18; i++) // next 18 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
}
+
+ // Potential overflow now processing the 20th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if ((ulong)answer > ulong.MaxValue / 10 || ((ulong)answer == ulong.MaxValue / 10 && num > '5'))
+ {
+ overflow = true;
+ }
+ answer = answer * 10 + num - '0';
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow || (hasNegativeSign && answer != 0))
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ result = (ulong)answer;
+ return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
+ }
+
+ /// <summary>Parses ulong limited to styles that make up NumberStyles.HexNumber.</summary>
+ private static bool TryParseUInt64HexNumberStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out ulong result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ int index = 0;
+ int num = value[0];
+ int numValue = 0;
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
+ }
+
+ long answer = 0;
+ int[] charToHexLookup = s_charToHexLookup;
+
+ if ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ // Skip past leading zeros.
+ if (num == '0')
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ } while (num == '0');
+ if ((uint)num >= (uint)charToHexLookup.Length || charToHexLookup[num] == 0xFF) goto HasTrailingChars;
+ }
+
+ // Parse up through 16 digits, as no overflow is possible
+ answer = charToHexLookup[num]; // first digit
+ index++;
+ for (int i = 0; i < 15; i++) // next 15 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ answer = 16 * answer + numValue;
+ }
+
+ // If there's another digit, it's an overflow.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ overflow = true;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility. Read through any remaining digits.
+ num = value[index];
+ while ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
}
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ DoneAtEnd:
+ result = (ulong)answer;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static decimal ParseDecimal(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ internal static decimal ParseDecimal(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
NumberBuffer number = default;
decimal result = 0;
- StringToNumber(value, options, ref number, numfmt, true);
+ StringToNumber(value, styles, ref number, info, true);
if (!NumberBufferToDecimal(ref number, ref result))
{
- throw new OverflowException(SR.Overflow_Decimal);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Decimal));
}
return result;
}
- internal unsafe static double ParseDouble(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ private static unsafe bool NumberBufferToDecimal(ref NumberBuffer number, ref decimal value)
+ {
+ char* p = number.digits;
+ int e = number.scale;
+ bool sign = number.sign;
+ uint c = *p;
+ if (c == 0)
+ {
+ // To avoid risking an app-compat issue with pre 4.5 (where some app was illegally using Reflection to examine the internal scale bits), we'll only force
+ // the scale to 0 if the scale was previously positive (previously, such cases were unparsable to a bug.)
+ value = new decimal(0, 0, 0, sign, (byte)Math.Clamp(-e, 0, 28));
+ return true;
+ }
+
+ if (e > DecimalPrecision)
+ return false;
+
+ ulong low64 = 0;
+ while (e > -28)
+ {
+ e--;
+ low64 *= 10;
+ low64 += c - '0';
+ c = *++p;
+ if (low64 >= ulong.MaxValue / 10)
+ break;
+ if (c == 0)
+ {
+ while (e > 0)
+ {
+ e--;
+ low64 *= 10;
+ if (low64 >= ulong.MaxValue / 10)
+ break;
+ }
+ break;
+ }
+ }
+
+ uint high = 0;
+ while ((e > 0 || (c != 0 && e > -28)) &&
+ (high < uint.MaxValue / 10 || (high == uint.MaxValue / 10 && (low64 < 0x99999999_99999999 || (low64 == 0x99999999_99999999 && c <= '5')))))
+ {
+ // multiply by 10
+ ulong tmpLow = (uint)low64 * 10UL;
+ ulong tmp64 = (uint)(low64 >> 32) * 10UL + (tmpLow >> 32);
+ low64 = (uint)tmpLow + (tmp64 << 32);
+ high = (uint)(tmp64 >> 32) + high * 10;
+
+ if (c != 0)
+ {
+ c -= '0';
+ low64 += c;
+ if (low64 < c)
+ high++;
+ c = *++p;
+ }
+ e--;
+ }
+
+ if (c >= '5')
+ {
+ // If the next digit is 5, round up if the number is odd or any following digit is non-zero
+ if (c == '5' && (low64 & 1) == 0)
+ {
+ c = *++p;
+ int count = 20; // Look at the next 20 digits to check to round
+ while (c == '0' && count != 0)
+ {
+ c = *++p;
+ count--;
+ }
+ if (c == 0 || count == 0)
+ goto NoRounding;// Do nothing
+ }
+
+ if (++low64 == 0 && ++high == 0)
+ {
+ low64 = 0x99999999_9999999A;
+ high = uint.MaxValue / 10;
+ e++;
+ }
+ }
+ NoRounding:
+
+ if (e > 0)
+ return false;
+
+ if (e <= -DecimalPrecision)
+ {
+ // Parsing a large scale zero can give you more precision than fits in the decimal.
+ // This should only happen for actual zeros or very small numbers that round to zero.
+ value = new decimal(0, 0, 0, sign, DecimalPrecision - 1);
+ }
+ else
+ {
+ value = new decimal((int)low64, (int)(low64 >> 32), (int)high, sign, (byte)-e);
+ }
+ return true;
+ }
+
+ internal static double ParseDouble(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
NumberBuffer number = default;
double d = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
//If we failed TryStringToNumber, it may be from one of our special strings.
//Check the three with which we're concerned and rethrow if it's not one of
//those strings.
ReadOnlySpan<char> sTrim = value.Trim();
- if (StringSpanHelpers.Equals(sTrim, numfmt.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
return double.PositiveInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NegativeInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
return double.NegativeInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NaNSymbol))
+ if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
return double.NaN;
}
- throw new FormatException(SR.Format_InvalidString);
+ ThrowOverflowOrFormatException(overflow: false, null);
}
if (!NumberBufferToDouble(ref number, ref d))
{
- throw new OverflowException(SR.Overflow_Double);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Double));
}
return d;
}
- internal unsafe static float ParseSingle(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ internal static float ParseSingle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
NumberBuffer number = default;
double d = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
//If we failed TryStringToNumber, it may be from one of our special strings.
//Check the three with which we're concerned and rethrow if it's not one of
//those strings.
ReadOnlySpan<char> sTrim = value.Trim();
- if (StringSpanHelpers.Equals(sTrim, numfmt.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
return float.PositiveInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NegativeInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
return float.NegativeInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NaNSymbol))
+ if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
return float.NaN;
}
- throw new FormatException(SR.Format_InvalidString);
+ ThrowOverflowOrFormatException(overflow: false, null);
}
if (!NumberBufferToDouble(ref number, ref d))
{
- throw new OverflowException(SR.Overflow_Single);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Single));
}
float castSingle = (float)d;
if (float.IsInfinity(castSingle))
{
- throw new OverflowException(SR.Overflow_Single);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Single));
}
return castSingle;
}
- internal unsafe static bool TryParseDecimal(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt, out decimal result)
+ internal static bool TryParseDecimal(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out decimal result)
{
NumberBuffer number = default;
result = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, true))
+ if (!TryStringToNumber(value, styles, ref number, info, true))
{
return false;
}
@@ -812,13 +1660,12 @@ namespace System
return true;
}
- internal unsafe static bool TryParseDouble(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt, out double result)
+ internal static bool TryParseDouble(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out double result)
{
NumberBuffer number = default;
result = 0;
-
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
return false;
}
@@ -829,13 +1676,13 @@ namespace System
return true;
}
- internal unsafe static bool TryParseSingle(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt, out float result)
+ internal static bool TryParseSingle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out float result)
{
NumberBuffer number = default;
result = 0;
double d = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
return false;
}
@@ -853,28 +1700,28 @@ namespace System
return true;
}
- private static unsafe void StringToNumber(ReadOnlySpan<char> str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
+ private static unsafe void StringToNumber(ReadOnlySpan<char> value, NumberStyles styles, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
Debug.Assert(info != null);
- fixed (char* stringPointer = &MemoryMarshal.GetReference(str))
+ fixed (char* stringPointer = &MemoryMarshal.GetReference(value))
{
char* p = stringPointer;
- if (!ParseNumber(ref p, options, ref number, info, parseDecimal)
- || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer))))
+ if (!ParseNumber(ref p, p + value.Length, styles, ref number, info, parseDecimal)
+ || (p - stringPointer < value.Length && !TrailingZeros(value, (int)(p - stringPointer))))
{
- throw new FormatException(SR.Format_InvalidString);
+ ThrowOverflowOrFormatException(overflow: false, null);
}
}
}
- internal static unsafe bool TryStringToNumber(ReadOnlySpan<char> str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo numfmt, bool parseDecimal)
+ internal static unsafe bool TryStringToNumber(ReadOnlySpan<char> value, NumberStyles styles, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
- Debug.Assert(numfmt != null);
- fixed (char* stringPointer = &MemoryMarshal.GetReference(str))
+ Debug.Assert(info != null);
+ fixed (char* stringPointer = &MemoryMarshal.GetReference(value))
{
char* p = stringPointer;
- if (!ParseNumber(ref p, options, ref number, numfmt, parseDecimal)
- || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer))))
+ if (!ParseNumber(ref p, p + value.Length, styles, ref number, info, parseDecimal)
+ || (p - stringPointer < value.Length && !TrailingZeros(value, (int)(p - stringPointer))))
{
return false;
}
@@ -883,12 +1730,12 @@ namespace System
return true;
}
- private static bool TrailingZeros(ReadOnlySpan<char> s, int index)
+ private static bool TrailingZeros(ReadOnlySpan<char> value, int index)
{
// For compatibility, we need to allow trailing zeros at the end of a number string
- for (int i = index; i < s.Length; i++)
+ for (int i = index; i < value.Length; i++)
{
- if (s[i] != '\0')
+ if (value[i] != '\0')
{
return false;
}
@@ -897,68 +1744,62 @@ namespace System
return true;
}
- private unsafe static char* MatchChars(char* p, string str)
+ private static unsafe char* MatchChars(char* p, char* pEnd, string value)
{
- fixed (char* stringPointer = str)
+ Debug.Assert(p != null && pEnd != null && p <= pEnd && value != null);
+ fixed (char* stringPointer = value)
{
- return MatchChars(p, stringPointer);
+ char* str = stringPointer;
+ if (*str != '\0')
+ {
+ // We only hurt the failure case
+ // This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a
+ // space character we use 0x20 space character instead to mean the same.
+ while (true)
+ {
+ char cp = p < pEnd ? *p : '\0';
+ if (cp != *str && !(*str == '\u00a0' && cp == '\u0020'))
+ {
+ break;
+ }
+ p++;
+ str++;
+ if (*str == '\0') return p;
+ }
+ }
}
+
+ return null;
}
- private unsafe static char* MatchChars(char* p, char* str)
- {
- Debug.Assert(p != null && str != null);
+ private static bool IsWhite(int ch) => ch == 0x20 || ((uint)(ch - 0x09) <= (0x0D - 0x09));
- if (*str == '\0')
- {
- return null;
- }
-
- // We only hurt the failure case
- // This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a
- // space character we use 0x20 space character instead to mean the same.
- while (*p == *str || (*str == '\u00a0' && *p == '\u0020'))
- {
- p++;
- str++;
- if (*str == '\0') return p;
- }
+ private static bool IsDigit(int ch) => ((uint)ch - '0') <= 9;
- return null;
+ private static void ThrowOverflowOrFormatException(bool overflow, string overflowResourceKey)
+ {
+ throw overflow ?
+ new OverflowException(SR.GetResourceString(overflowResourceKey)) :
+ (Exception)new FormatException(SR.Format_InvalidString);
}
- private static bool IsWhite(char ch) => ch == 0x20 || (ch >= 0x09 && ch <= 0x0D);
-
private static bool NumberBufferToDouble(ref NumberBuffer number, ref double value)
{
double d = NumberToDouble(ref number);
- uint e = DoubleHelper.Exponent(d);
- ulong m = DoubleHelper.Mantissa(d);
-
- if (e == 0x7FF)
+ if (!double.IsFinite(d))
{
+ value = default;
return false;
}
- if (e == 0 && m == 0)
+ if (d == 0.0)
{
- d = 0;
+ // normalize -0.0 to 0.0
+ d = 0.0;
}
value = d;
return true;
}
-
- private static class DoubleHelper
- {
- public static unsafe uint Exponent(double d) =>
- (*((uint*)&d + 1) >> 20) & 0x000007ff;
-
- public static unsafe ulong Mantissa(double d) =>
- *((ulong*)&d) & 0x000fffffffffffff;
-
- public static unsafe bool Sign(double d) =>
- (*((uint*)&d + 1) >> 31) != 0;
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs
index ea32ed380..3fb3086b2 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs
@@ -9,131 +9,131 @@ namespace System.Numerics
internal class ConstantHelper
{
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Byte GetByteWithAllBitsSet()
+ public static byte GetByteWithAllBitsSet()
{
- Byte value = 0;
+ byte value = 0;
unsafe
{
unchecked
{
- *((Byte*)&value) = (Byte)0xff;
+ *((byte*)&value) = (byte)0xff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static SByte GetSByteWithAllBitsSet()
+ public static sbyte GetSByteWithAllBitsSet()
{
- SByte value = 0;
+ sbyte value = 0;
unsafe
{
unchecked
{
- *((SByte*)&value) = (SByte)0xff;
+ *((sbyte*)&value) = (sbyte)0xff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static UInt16 GetUInt16WithAllBitsSet()
+ public static ushort GetUInt16WithAllBitsSet()
{
- UInt16 value = 0;
+ ushort value = 0;
unsafe
{
unchecked
{
- *((UInt16*)&value) = (UInt16)0xffff;
+ *((ushort*)&value) = (ushort)0xffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Int16 GetInt16WithAllBitsSet()
+ public static short GetInt16WithAllBitsSet()
{
- Int16 value = 0;
+ short value = 0;
unsafe
{
unchecked
{
- *((Int16*)&value) = (Int16)0xffff;
+ *((short*)&value) = (short)0xffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static UInt32 GetUInt32WithAllBitsSet()
+ public static uint GetUInt32WithAllBitsSet()
{
- UInt32 value = 0;
+ uint value = 0;
unsafe
{
unchecked
{
- *((UInt32*)&value) = (UInt32)0xffffffff;
+ *((uint*)&value) = (uint)0xffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Int32 GetInt32WithAllBitsSet()
+ public static int GetInt32WithAllBitsSet()
{
- Int32 value = 0;
+ int value = 0;
unsafe
{
unchecked
{
- *((Int32*)&value) = (Int32)0xffffffff;
+ *((int*)&value) = (int)0xffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static UInt64 GetUInt64WithAllBitsSet()
+ public static ulong GetUInt64WithAllBitsSet()
{
- UInt64 value = 0;
+ ulong value = 0;
unsafe
{
unchecked
{
- *((UInt64*)&value) = (UInt64)0xffffffffffffffff;
+ *((ulong*)&value) = (ulong)0xffffffffffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Int64 GetInt64WithAllBitsSet()
+ public static long GetInt64WithAllBitsSet()
{
- Int64 value = 0;
+ long value = 0;
unsafe
{
unchecked
{
- *((Int64*)&value) = (Int64)0xffffffffffffffff;
+ *((long*)&value) = (long)0xffffffffffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Single GetSingleWithAllBitsSet()
+ public static float GetSingleWithAllBitsSet()
{
- Single value = 0;
+ float value = 0;
unsafe
{
unchecked
{
- *((Int32*)&value) = (Int32)0xffffffff;
+ *((int*)&value) = (int)0xffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Double GetDoubleWithAllBitsSet()
+ public static double GetDoubleWithAllBitsSet()
{
- Double value = 0;
+ double value = 0;
unsafe
{
unchecked
{
- *((Int64*)&value) = (Int64)0xffffffffffffffff;
+ *((long*)&value) = (long)0xffffffffffffffff;
}
}
return value;
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt
index 4b1c67757..dd823abc0 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt
+++ b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt
@@ -20,19 +20,20 @@ namespace System.Numerics
{
internal class ConstantHelper
{
-<# foreach (var type in supportedTypes)
+<#
+ foreach (var type in supportedTypes)
{
string hexValue = "0x" + new string('f', Marshal.SizeOf(type) * 2);
#>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static <#= type.Name #> Get<#= type.Name #>WithAllBitsSet()
+ public static <#= typeAliases[type] #> Get<#= type.Name #>WithAllBitsSet()
{
- <#= type.Name #> value = 0;
+ <#= typeAliases[type] #> value = 0;
unsafe
{
unchecked
{
- *((<#= GetIntegralEquivalent(type).Name #>*)&value) = (<#=GetIntegralEquivalent(type).Name#>)<#= hexValue #>;
+ *((<#= typeAliases[GetIntegralEquivalent(type)] #>*)&value) = (<#= typeAliases[GetIntegralEquivalent(type)] #>)<#= hexValue #>;
}
}
return value;
@@ -44,17 +45,17 @@ namespace System.Numerics
}<#+
public Type GetIntegralEquivalent(Type type)
{
- if (type == typeof(Single))
+ if (type == typeof(float))
{
- return typeof(Int32);
+ return typeof(int);
}
else if (type == typeof(double))
{
- return typeof(Int64);
+ return typeof(long);
}
else
{
return type;
}
}
-#> \ No newline at end of file
+#>
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude b/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude
index cdd9c9521..a4466e1a8 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude
+++ b/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude
@@ -1,5 +1,6 @@
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Text" #>
<#+
/* This file includes static data used as compilation configuration for the rest of the code generation.
It is shared here to ensure that all generated code compiles with the same constants and configurations. */
@@ -7,27 +8,40 @@
// The set of supported numeric types to compile
public static Type[] supportedTypes = new[]
{
- typeof(Byte), typeof(SByte), typeof(UInt16), typeof(Int16),
- typeof(UInt32), typeof(Int32), typeof(UInt64), typeof(Int64),
- typeof(Single), typeof(Double)
+ typeof(byte), typeof(sbyte), typeof(ushort), typeof(short),
+ typeof(uint), typeof(int), typeof(ulong), typeof(long),
+ typeof(float), typeof(double)
};
// The set of unsigned types, a subset of the above. Used for excluding from certain methods, i.e. Abs and Negate
public static Type[] unsignedTypes = new[]
{
- typeof(Byte), typeof(UInt16), typeof(UInt32), typeof(UInt64)
+ typeof(byte), typeof(ushort), typeof(uint), typeof(ulong)
};
public static Type[] integralTypes = new[]
{
- typeof(Byte), typeof(SByte), typeof(UInt16), typeof(Int16),
- typeof(UInt32), typeof(Int32), typeof(UInt64), typeof(Int64)
+ typeof(byte), typeof(sbyte), typeof(ushort), typeof(short),
+ typeof(uint), typeof(int), typeof(ulong), typeof(long)
};
public static Type[] nonClsCompliantTypes = new[]
{
- typeof(SByte), typeof(UInt16),
- typeof(UInt32), typeof(UInt64)
+ typeof(sbyte), typeof(ushort), typeof(uint), typeof(ulong)
+ };
+
+ public static Dictionary<Type, string> typeAliases = new Dictionary<Type, string>()
+ {
+ { typeof(byte), "byte" },
+ { typeof(sbyte), "sbyte" },
+ { typeof(ushort), "ushort" },
+ { typeof(short), "short" },
+ { typeof(uint), "uint" },
+ { typeof(int), "int" },
+ { typeof(ulong), "ulong" },
+ { typeof(long), "long" },
+ { typeof(float), "float" },
+ { typeof(double), "double" }
};
// The total register size, in bytes. 16 for SSE2, 32 for AVX, 64 for AVX512
@@ -136,12 +150,37 @@
public string GenerateIfStatementHeader(Type type)
{
string keyword = (type == supportedTypes[0]) ? "if" : "else if";
- return string.Format("{0} (typeof(T) == typeof({1}))", keyword, type.Name);
+ return string.Format("{0} (typeof(T) == typeof({1}))", keyword, typeAliases[type]);
}
public string GenerateIfStatementHeader(Type type, IEnumerable<Type> allTypes)
{
string keyword = (type == allTypes.ToArray()[0]) ? "if" : "else if";
- return string.Format("{0} (typeof(T) == typeof({1}))", keyword, type.Name);
+ return string.Format("{0} (typeof(T) == typeof({1}))", keyword, typeAliases[type]);
+ }
+
+ public string MakeTypeComparisonCondition(Type type)
+ {
+ return string.Format("(typeof(T) == typeof({0}))", typeAliases[type]);
+ }
+
+ public string GenerateIfConditionAllTypes(IEnumerable<Type> allTypes)
+ {
+ StringBuilder sbuilder = new StringBuilder();
+ bool firstTime = true;
+ foreach (var type in allTypes)
+ {
+ if (firstTime)
+ {
+ sbuilder.Append("if (").Append(MakeTypeComparisonCondition(type));
+ firstTime = false;
+ }
+ else
+ {
+ sbuilder.AppendLine().Append(" || ").Append(MakeTypeComparisonCondition(type));
+ }
+ }
+ sbuilder.Append(")");
+ return sbuilder.ToString();
}
-#> \ No newline at end of file
+#>
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Register.cs b/src/System.Private.CoreLib/shared/System/Numerics/Register.cs
index a27e922b9..8efa85b19 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Register.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Register.cs
@@ -17,155 +17,155 @@ namespace System.Numerics
#region Internal Storage Fields
// Internal System.Byte Fields
[FieldOffset(0)]
- internal Byte byte_0;
+ internal byte byte_0;
[FieldOffset(1)]
- internal Byte byte_1;
+ internal byte byte_1;
[FieldOffset(2)]
- internal Byte byte_2;
+ internal byte byte_2;
[FieldOffset(3)]
- internal Byte byte_3;
+ internal byte byte_3;
[FieldOffset(4)]
- internal Byte byte_4;
+ internal byte byte_4;
[FieldOffset(5)]
- internal Byte byte_5;
+ internal byte byte_5;
[FieldOffset(6)]
- internal Byte byte_6;
+ internal byte byte_6;
[FieldOffset(7)]
- internal Byte byte_7;
+ internal byte byte_7;
[FieldOffset(8)]
- internal Byte byte_8;
+ internal byte byte_8;
[FieldOffset(9)]
- internal Byte byte_9;
+ internal byte byte_9;
[FieldOffset(10)]
- internal Byte byte_10;
+ internal byte byte_10;
[FieldOffset(11)]
- internal Byte byte_11;
+ internal byte byte_11;
[FieldOffset(12)]
- internal Byte byte_12;
+ internal byte byte_12;
[FieldOffset(13)]
- internal Byte byte_13;
+ internal byte byte_13;
[FieldOffset(14)]
- internal Byte byte_14;
+ internal byte byte_14;
[FieldOffset(15)]
- internal Byte byte_15;
+ internal byte byte_15;
// Internal System.SByte Fields
[FieldOffset(0)]
- internal SByte sbyte_0;
+ internal sbyte sbyte_0;
[FieldOffset(1)]
- internal SByte sbyte_1;
+ internal sbyte sbyte_1;
[FieldOffset(2)]
- internal SByte sbyte_2;
+ internal sbyte sbyte_2;
[FieldOffset(3)]
- internal SByte sbyte_3;
+ internal sbyte sbyte_3;
[FieldOffset(4)]
- internal SByte sbyte_4;
+ internal sbyte sbyte_4;
[FieldOffset(5)]
- internal SByte sbyte_5;
+ internal sbyte sbyte_5;
[FieldOffset(6)]
- internal SByte sbyte_6;
+ internal sbyte sbyte_6;
[FieldOffset(7)]
- internal SByte sbyte_7;
+ internal sbyte sbyte_7;
[FieldOffset(8)]
- internal SByte sbyte_8;
+ internal sbyte sbyte_8;
[FieldOffset(9)]
- internal SByte sbyte_9;
+ internal sbyte sbyte_9;
[FieldOffset(10)]
- internal SByte sbyte_10;
+ internal sbyte sbyte_10;
[FieldOffset(11)]
- internal SByte sbyte_11;
+ internal sbyte sbyte_11;
[FieldOffset(12)]
- internal SByte sbyte_12;
+ internal sbyte sbyte_12;
[FieldOffset(13)]
- internal SByte sbyte_13;
+ internal sbyte sbyte_13;
[FieldOffset(14)]
- internal SByte sbyte_14;
+ internal sbyte sbyte_14;
[FieldOffset(15)]
- internal SByte sbyte_15;
+ internal sbyte sbyte_15;
// Internal System.UInt16 Fields
[FieldOffset(0)]
- internal UInt16 uint16_0;
+ internal ushort uint16_0;
[FieldOffset(2)]
- internal UInt16 uint16_1;
+ internal ushort uint16_1;
[FieldOffset(4)]
- internal UInt16 uint16_2;
+ internal ushort uint16_2;
[FieldOffset(6)]
- internal UInt16 uint16_3;
+ internal ushort uint16_3;
[FieldOffset(8)]
- internal UInt16 uint16_4;
+ internal ushort uint16_4;
[FieldOffset(10)]
- internal UInt16 uint16_5;
+ internal ushort uint16_5;
[FieldOffset(12)]
- internal UInt16 uint16_6;
+ internal ushort uint16_6;
[FieldOffset(14)]
- internal UInt16 uint16_7;
+ internal ushort uint16_7;
// Internal System.Int16 Fields
[FieldOffset(0)]
- internal Int16 int16_0;
+ internal short int16_0;
[FieldOffset(2)]
- internal Int16 int16_1;
+ internal short int16_1;
[FieldOffset(4)]
- internal Int16 int16_2;
+ internal short int16_2;
[FieldOffset(6)]
- internal Int16 int16_3;
+ internal short int16_3;
[FieldOffset(8)]
- internal Int16 int16_4;
+ internal short int16_4;
[FieldOffset(10)]
- internal Int16 int16_5;
+ internal short int16_5;
[FieldOffset(12)]
- internal Int16 int16_6;
+ internal short int16_6;
[FieldOffset(14)]
- internal Int16 int16_7;
+ internal short int16_7;
// Internal System.UInt32 Fields
[FieldOffset(0)]
- internal UInt32 uint32_0;
+ internal uint uint32_0;
[FieldOffset(4)]
- internal UInt32 uint32_1;
+ internal uint uint32_1;
[FieldOffset(8)]
- internal UInt32 uint32_2;
+ internal uint uint32_2;
[FieldOffset(12)]
- internal UInt32 uint32_3;
+ internal uint uint32_3;
// Internal System.Int32 Fields
[FieldOffset(0)]
- internal Int32 int32_0;
+ internal int int32_0;
[FieldOffset(4)]
- internal Int32 int32_1;
+ internal int int32_1;
[FieldOffset(8)]
- internal Int32 int32_2;
+ internal int int32_2;
[FieldOffset(12)]
- internal Int32 int32_3;
+ internal int int32_3;
// Internal System.UInt64 Fields
[FieldOffset(0)]
- internal UInt64 uint64_0;
+ internal ulong uint64_0;
[FieldOffset(8)]
- internal UInt64 uint64_1;
+ internal ulong uint64_1;
// Internal System.Int64 Fields
[FieldOffset(0)]
- internal Int64 int64_0;
+ internal long int64_0;
[FieldOffset(8)]
- internal Int64 int64_1;
+ internal long int64_1;
// Internal System.Single Fields
[FieldOffset(0)]
- internal Single single_0;
+ internal float single_0;
[FieldOffset(4)]
- internal Single single_1;
+ internal float single_1;
[FieldOffset(8)]
- internal Single single_2;
+ internal float single_2;
[FieldOffset(12)]
- internal Single single_3;
+ internal float single_3;
// Internal System.Double Fields
[FieldOffset(0)]
- internal Double double_0;
+ internal double double_0;
[FieldOffset(8)]
- internal Double double_1;
+ internal double double_1;
#endregion Internal Storage Fields
}
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Register.tt b/src/System.Private.CoreLib/shared/System/Numerics/Register.tt
index a9de3b974..676b89f54 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Register.tt
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Register.tt
@@ -34,7 +34,7 @@ namespace System.Numerics
{
#>
[FieldOffset(<#=Marshal.SizeOf(type) * g#>)]
- internal <#=type.Name#> <#= type.Name.ToLowerInvariant() + "_" + g #>;
+ internal <#= typeAliases[type] #> <#= type.Name.ToLowerInvariant() + "_" + g #>;
<#
}
#>
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs b/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs
index 5fd286732..31a9114e3 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs
@@ -2,9 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#if netcoreapp
+using Internal.Runtime.CompilerServices;
+#endif
using System.Globalization;
using System.Numerics.Hashing;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
namespace System.Numerics
@@ -12,8 +16,8 @@ namespace System.Numerics
/* Note: The following patterns are used throughout the code here and are described here
*
* PATTERN:
- * if (typeof(T) == typeof(Int32)) { ... }
- * else if (typeof(T) == typeof(Single)) { ... }
+ * if (typeof(T) == typeof(int)) { ... }
+ * else if (typeof(T) == typeof(float)) { ... }
* EXPLANATION:
* At runtime, each instantiation of Vector<T> will be type-specific, and each of these typeof blocks will be eliminated,
* as typeof(T) is a (JIT) compile-time constant for each instantiation. This design was chosen to eliminate any overhead from
@@ -96,7 +100,7 @@ namespace System.Numerics
internal byte _byte;
}
- // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
+ // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
private static unsafe int InitializeCount()
{
VectorSizeHelper vsh;
@@ -105,45 +109,45 @@ namespace System.Numerics
int vectorSizeInBytes = (int)(byteBase - vectorBase);
int typeSizeInBytes = -1;
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- typeSizeInBytes = sizeof(Byte);
+ typeSizeInBytes = sizeof(byte);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- typeSizeInBytes = sizeof(SByte);
+ typeSizeInBytes = sizeof(sbyte);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- typeSizeInBytes = sizeof(UInt16);
+ typeSizeInBytes = sizeof(ushort);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- typeSizeInBytes = sizeof(Int16);
+ typeSizeInBytes = sizeof(short);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- typeSizeInBytes = sizeof(UInt32);
+ typeSizeInBytes = sizeof(uint);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- typeSizeInBytes = sizeof(Int32);
+ typeSizeInBytes = sizeof(int);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- typeSizeInBytes = sizeof(UInt64);
+ typeSizeInBytes = sizeof(ulong);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- typeSizeInBytes = sizeof(Int64);
+ typeSizeInBytes = sizeof(long);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- typeSizeInBytes = sizeof(Single);
+ typeSizeInBytes = sizeof(float);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- typeSizeInBytes = sizeof(Double);
+ typeSizeInBytes = sizeof(double);
}
else
{
@@ -164,204 +168,204 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Byte)(object)value;
+ *(basePtr + g) = (byte)(object)value;
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (SByte)(object)value;
+ *(basePtr + g) = (sbyte)(object)value;
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt16)(object)value;
+ *(basePtr + g) = (ushort)(object)value;
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int16)(object)value;
+ *(basePtr + g) = (short)(object)value;
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt32)(object)value;
+ *(basePtr + g) = (uint)(object)value;
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int32)(object)value;
+ *(basePtr + g) = (int)(object)value;
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt64)(object)value;
+ *(basePtr + g) = (ulong)(object)value;
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int64)(object)value;
+ *(basePtr + g) = (long)(object)value;
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Single)(object)value;
+ *(basePtr + g) = (float)(object)value;
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Double)(object)value;
+ *(basePtr + g) = (double)(object)value;
}
}
}
}
else
{
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = (Byte)(object)value;
- register.byte_1 = (Byte)(object)value;
- register.byte_2 = (Byte)(object)value;
- register.byte_3 = (Byte)(object)value;
- register.byte_4 = (Byte)(object)value;
- register.byte_5 = (Byte)(object)value;
- register.byte_6 = (Byte)(object)value;
- register.byte_7 = (Byte)(object)value;
- register.byte_8 = (Byte)(object)value;
- register.byte_9 = (Byte)(object)value;
- register.byte_10 = (Byte)(object)value;
- register.byte_11 = (Byte)(object)value;
- register.byte_12 = (Byte)(object)value;
- register.byte_13 = (Byte)(object)value;
- register.byte_14 = (Byte)(object)value;
- register.byte_15 = (Byte)(object)value;
- }
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = (SByte)(object)value;
- register.sbyte_1 = (SByte)(object)value;
- register.sbyte_2 = (SByte)(object)value;
- register.sbyte_3 = (SByte)(object)value;
- register.sbyte_4 = (SByte)(object)value;
- register.sbyte_5 = (SByte)(object)value;
- register.sbyte_6 = (SByte)(object)value;
- register.sbyte_7 = (SByte)(object)value;
- register.sbyte_8 = (SByte)(object)value;
- register.sbyte_9 = (SByte)(object)value;
- register.sbyte_10 = (SByte)(object)value;
- register.sbyte_11 = (SByte)(object)value;
- register.sbyte_12 = (SByte)(object)value;
- register.sbyte_13 = (SByte)(object)value;
- register.sbyte_14 = (SByte)(object)value;
- register.sbyte_15 = (SByte)(object)value;
- }
- else if (typeof(T) == typeof(UInt16))
- {
- register.uint16_0 = (UInt16)(object)value;
- register.uint16_1 = (UInt16)(object)value;
- register.uint16_2 = (UInt16)(object)value;
- register.uint16_3 = (UInt16)(object)value;
- register.uint16_4 = (UInt16)(object)value;
- register.uint16_5 = (UInt16)(object)value;
- register.uint16_6 = (UInt16)(object)value;
- register.uint16_7 = (UInt16)(object)value;
- }
- else if (typeof(T) == typeof(Int16))
- {
- register.int16_0 = (Int16)(object)value;
- register.int16_1 = (Int16)(object)value;
- register.int16_2 = (Int16)(object)value;
- register.int16_3 = (Int16)(object)value;
- register.int16_4 = (Int16)(object)value;
- register.int16_5 = (Int16)(object)value;
- register.int16_6 = (Int16)(object)value;
- register.int16_7 = (Int16)(object)value;
- }
- else if (typeof(T) == typeof(UInt32))
- {
- register.uint32_0 = (UInt32)(object)value;
- register.uint32_1 = (UInt32)(object)value;
- register.uint32_2 = (UInt32)(object)value;
- register.uint32_3 = (UInt32)(object)value;
- }
- else if (typeof(T) == typeof(Int32))
- {
- register.int32_0 = (Int32)(object)value;
- register.int32_1 = (Int32)(object)value;
- register.int32_2 = (Int32)(object)value;
- register.int32_3 = (Int32)(object)value;
- }
- else if (typeof(T) == typeof(UInt64))
- {
- register.uint64_0 = (UInt64)(object)value;
- register.uint64_1 = (UInt64)(object)value;
- }
- else if (typeof(T) == typeof(Int64))
- {
- register.int64_0 = (Int64)(object)value;
- register.int64_1 = (Int64)(object)value;
- }
- else if (typeof(T) == typeof(Single))
- {
- register.single_0 = (Single)(object)value;
- register.single_1 = (Single)(object)value;
- register.single_2 = (Single)(object)value;
- register.single_3 = (Single)(object)value;
- }
- else if (typeof(T) == typeof(Double))
- {
- register.double_0 = (Double)(object)value;
- register.double_1 = (Double)(object)value;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = (byte)(object)value;
+ register.byte_1 = (byte)(object)value;
+ register.byte_2 = (byte)(object)value;
+ register.byte_3 = (byte)(object)value;
+ register.byte_4 = (byte)(object)value;
+ register.byte_5 = (byte)(object)value;
+ register.byte_6 = (byte)(object)value;
+ register.byte_7 = (byte)(object)value;
+ register.byte_8 = (byte)(object)value;
+ register.byte_9 = (byte)(object)value;
+ register.byte_10 = (byte)(object)value;
+ register.byte_11 = (byte)(object)value;
+ register.byte_12 = (byte)(object)value;
+ register.byte_13 = (byte)(object)value;
+ register.byte_14 = (byte)(object)value;
+ register.byte_15 = (byte)(object)value;
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = (sbyte)(object)value;
+ register.sbyte_1 = (sbyte)(object)value;
+ register.sbyte_2 = (sbyte)(object)value;
+ register.sbyte_3 = (sbyte)(object)value;
+ register.sbyte_4 = (sbyte)(object)value;
+ register.sbyte_5 = (sbyte)(object)value;
+ register.sbyte_6 = (sbyte)(object)value;
+ register.sbyte_7 = (sbyte)(object)value;
+ register.sbyte_8 = (sbyte)(object)value;
+ register.sbyte_9 = (sbyte)(object)value;
+ register.sbyte_10 = (sbyte)(object)value;
+ register.sbyte_11 = (sbyte)(object)value;
+ register.sbyte_12 = (sbyte)(object)value;
+ register.sbyte_13 = (sbyte)(object)value;
+ register.sbyte_14 = (sbyte)(object)value;
+ register.sbyte_15 = (sbyte)(object)value;
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ register.uint16_0 = (ushort)(object)value;
+ register.uint16_1 = (ushort)(object)value;
+ register.uint16_2 = (ushort)(object)value;
+ register.uint16_3 = (ushort)(object)value;
+ register.uint16_4 = (ushort)(object)value;
+ register.uint16_5 = (ushort)(object)value;
+ register.uint16_6 = (ushort)(object)value;
+ register.uint16_7 = (ushort)(object)value;
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ register.int16_0 = (short)(object)value;
+ register.int16_1 = (short)(object)value;
+ register.int16_2 = (short)(object)value;
+ register.int16_3 = (short)(object)value;
+ register.int16_4 = (short)(object)value;
+ register.int16_5 = (short)(object)value;
+ register.int16_6 = (short)(object)value;
+ register.int16_7 = (short)(object)value;
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ register.uint32_0 = (uint)(object)value;
+ register.uint32_1 = (uint)(object)value;
+ register.uint32_2 = (uint)(object)value;
+ register.uint32_3 = (uint)(object)value;
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ register.int32_0 = (int)(object)value;
+ register.int32_1 = (int)(object)value;
+ register.int32_2 = (int)(object)value;
+ register.int32_3 = (int)(object)value;
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ register.uint64_0 = (ulong)(object)value;
+ register.uint64_1 = (ulong)(object)value;
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ register.int64_0 = (long)(object)value;
+ register.int64_1 = (long)(object)value;
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ register.single_0 = (float)(object)value;
+ register.single_1 = (float)(object)value;
+ register.single_2 = (float)(object)value;
+ register.single_3 = (float)(object)value;
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ register.double_0 = (double)(object)value;
+ register.double_1 = (double)(object)value;
}
}
}
@@ -386,238 +390,238 @@ namespace System.Numerics
}
if (index < 0 || (values.Length - index) < Count)
{
- throw new IndexOutOfRangeException();
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
}
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Byte)(object)values[g + index];
+ *(basePtr + g) = (byte)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (SByte)(object)values[g + index];
+ *(basePtr + g) = (sbyte)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt16)(object)values[g + index];
+ *(basePtr + g) = (ushort)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int16)(object)values[g + index];
+ *(basePtr + g) = (short)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt32)(object)values[g + index];
+ *(basePtr + g) = (uint)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int32)(object)values[g + index];
+ *(basePtr + g) = (int)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt64)(object)values[g + index];
+ *(basePtr + g) = (ulong)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int64)(object)values[g + index];
+ *(basePtr + g) = (long)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Single)(object)values[g + index];
+ *(basePtr + g) = (float)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Double)(object)values[g + index];
+ *(basePtr + g) = (double)(object)values[g + index];
}
}
}
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
- *(basePtr + 0) = (Byte)(object)values[0 + index];
- *(basePtr + 1) = (Byte)(object)values[1 + index];
- *(basePtr + 2) = (Byte)(object)values[2 + index];
- *(basePtr + 3) = (Byte)(object)values[3 + index];
- *(basePtr + 4) = (Byte)(object)values[4 + index];
- *(basePtr + 5) = (Byte)(object)values[5 + index];
- *(basePtr + 6) = (Byte)(object)values[6 + index];
- *(basePtr + 7) = (Byte)(object)values[7 + index];
- *(basePtr + 8) = (Byte)(object)values[8 + index];
- *(basePtr + 9) = (Byte)(object)values[9 + index];
- *(basePtr + 10) = (Byte)(object)values[10 + index];
- *(basePtr + 11) = (Byte)(object)values[11 + index];
- *(basePtr + 12) = (Byte)(object)values[12 + index];
- *(basePtr + 13) = (Byte)(object)values[13 + index];
- *(basePtr + 14) = (Byte)(object)values[14 + index];
- *(basePtr + 15) = (Byte)(object)values[15 + index];
+ *(basePtr + 0) = (byte)(object)values[0 + index];
+ *(basePtr + 1) = (byte)(object)values[1 + index];
+ *(basePtr + 2) = (byte)(object)values[2 + index];
+ *(basePtr + 3) = (byte)(object)values[3 + index];
+ *(basePtr + 4) = (byte)(object)values[4 + index];
+ *(basePtr + 5) = (byte)(object)values[5 + index];
+ *(basePtr + 6) = (byte)(object)values[6 + index];
+ *(basePtr + 7) = (byte)(object)values[7 + index];
+ *(basePtr + 8) = (byte)(object)values[8 + index];
+ *(basePtr + 9) = (byte)(object)values[9 + index];
+ *(basePtr + 10) = (byte)(object)values[10 + index];
+ *(basePtr + 11) = (byte)(object)values[11 + index];
+ *(basePtr + 12) = (byte)(object)values[12 + index];
+ *(basePtr + 13) = (byte)(object)values[13 + index];
+ *(basePtr + 14) = (byte)(object)values[14 + index];
+ *(basePtr + 15) = (byte)(object)values[15 + index];
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
- *(basePtr + 0) = (SByte)(object)values[0 + index];
- *(basePtr + 1) = (SByte)(object)values[1 + index];
- *(basePtr + 2) = (SByte)(object)values[2 + index];
- *(basePtr + 3) = (SByte)(object)values[3 + index];
- *(basePtr + 4) = (SByte)(object)values[4 + index];
- *(basePtr + 5) = (SByte)(object)values[5 + index];
- *(basePtr + 6) = (SByte)(object)values[6 + index];
- *(basePtr + 7) = (SByte)(object)values[7 + index];
- *(basePtr + 8) = (SByte)(object)values[8 + index];
- *(basePtr + 9) = (SByte)(object)values[9 + index];
- *(basePtr + 10) = (SByte)(object)values[10 + index];
- *(basePtr + 11) = (SByte)(object)values[11 + index];
- *(basePtr + 12) = (SByte)(object)values[12 + index];
- *(basePtr + 13) = (SByte)(object)values[13 + index];
- *(basePtr + 14) = (SByte)(object)values[14 + index];
- *(basePtr + 15) = (SByte)(object)values[15 + index];
+ *(basePtr + 0) = (sbyte)(object)values[0 + index];
+ *(basePtr + 1) = (sbyte)(object)values[1 + index];
+ *(basePtr + 2) = (sbyte)(object)values[2 + index];
+ *(basePtr + 3) = (sbyte)(object)values[3 + index];
+ *(basePtr + 4) = (sbyte)(object)values[4 + index];
+ *(basePtr + 5) = (sbyte)(object)values[5 + index];
+ *(basePtr + 6) = (sbyte)(object)values[6 + index];
+ *(basePtr + 7) = (sbyte)(object)values[7 + index];
+ *(basePtr + 8) = (sbyte)(object)values[8 + index];
+ *(basePtr + 9) = (sbyte)(object)values[9 + index];
+ *(basePtr + 10) = (sbyte)(object)values[10 + index];
+ *(basePtr + 11) = (sbyte)(object)values[11 + index];
+ *(basePtr + 12) = (sbyte)(object)values[12 + index];
+ *(basePtr + 13) = (sbyte)(object)values[13 + index];
+ *(basePtr + 14) = (sbyte)(object)values[14 + index];
+ *(basePtr + 15) = (sbyte)(object)values[15 + index];
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
- *(basePtr + 0) = (UInt16)(object)values[0 + index];
- *(basePtr + 1) = (UInt16)(object)values[1 + index];
- *(basePtr + 2) = (UInt16)(object)values[2 + index];
- *(basePtr + 3) = (UInt16)(object)values[3 + index];
- *(basePtr + 4) = (UInt16)(object)values[4 + index];
- *(basePtr + 5) = (UInt16)(object)values[5 + index];
- *(basePtr + 6) = (UInt16)(object)values[6 + index];
- *(basePtr + 7) = (UInt16)(object)values[7 + index];
+ *(basePtr + 0) = (ushort)(object)values[0 + index];
+ *(basePtr + 1) = (ushort)(object)values[1 + index];
+ *(basePtr + 2) = (ushort)(object)values[2 + index];
+ *(basePtr + 3) = (ushort)(object)values[3 + index];
+ *(basePtr + 4) = (ushort)(object)values[4 + index];
+ *(basePtr + 5) = (ushort)(object)values[5 + index];
+ *(basePtr + 6) = (ushort)(object)values[6 + index];
+ *(basePtr + 7) = (ushort)(object)values[7 + index];
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
- *(basePtr + 0) = (Int16)(object)values[0 + index];
- *(basePtr + 1) = (Int16)(object)values[1 + index];
- *(basePtr + 2) = (Int16)(object)values[2 + index];
- *(basePtr + 3) = (Int16)(object)values[3 + index];
- *(basePtr + 4) = (Int16)(object)values[4 + index];
- *(basePtr + 5) = (Int16)(object)values[5 + index];
- *(basePtr + 6) = (Int16)(object)values[6 + index];
- *(basePtr + 7) = (Int16)(object)values[7 + index];
+ *(basePtr + 0) = (short)(object)values[0 + index];
+ *(basePtr + 1) = (short)(object)values[1 + index];
+ *(basePtr + 2) = (short)(object)values[2 + index];
+ *(basePtr + 3) = (short)(object)values[3 + index];
+ *(basePtr + 4) = (short)(object)values[4 + index];
+ *(basePtr + 5) = (short)(object)values[5 + index];
+ *(basePtr + 6) = (short)(object)values[6 + index];
+ *(basePtr + 7) = (short)(object)values[7 + index];
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
- *(basePtr + 0) = (UInt32)(object)values[0 + index];
- *(basePtr + 1) = (UInt32)(object)values[1 + index];
- *(basePtr + 2) = (UInt32)(object)values[2 + index];
- *(basePtr + 3) = (UInt32)(object)values[3 + index];
+ *(basePtr + 0) = (uint)(object)values[0 + index];
+ *(basePtr + 1) = (uint)(object)values[1 + index];
+ *(basePtr + 2) = (uint)(object)values[2 + index];
+ *(basePtr + 3) = (uint)(object)values[3 + index];
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
- *(basePtr + 0) = (Int32)(object)values[0 + index];
- *(basePtr + 1) = (Int32)(object)values[1 + index];
- *(basePtr + 2) = (Int32)(object)values[2 + index];
- *(basePtr + 3) = (Int32)(object)values[3 + index];
+ *(basePtr + 0) = (int)(object)values[0 + index];
+ *(basePtr + 1) = (int)(object)values[1 + index];
+ *(basePtr + 2) = (int)(object)values[2 + index];
+ *(basePtr + 3) = (int)(object)values[3 + index];
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
- *(basePtr + 0) = (UInt64)(object)values[0 + index];
- *(basePtr + 1) = (UInt64)(object)values[1 + index];
+ *(basePtr + 0) = (ulong)(object)values[0 + index];
+ *(basePtr + 1) = (ulong)(object)values[1 + index];
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
- *(basePtr + 0) = (Int64)(object)values[0 + index];
- *(basePtr + 1) = (Int64)(object)values[1 + index];
+ *(basePtr + 0) = (long)(object)values[0 + index];
+ *(basePtr + 1) = (long)(object)values[1 + index];
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
- *(basePtr + 0) = (Single)(object)values[0 + index];
- *(basePtr + 1) = (Single)(object)values[1 + index];
- *(basePtr + 2) = (Single)(object)values[2 + index];
- *(basePtr + 3) = (Single)(object)values[3 + index];
+ *(basePtr + 0) = (float)(object)values[0 + index];
+ *(basePtr + 1) = (float)(object)values[1 + index];
+ *(basePtr + 2) = (float)(object)values[2 + index];
+ *(basePtr + 3) = (float)(object)values[3 + index];
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
- *(basePtr + 0) = (Double)(object)values[0 + index];
- *(basePtr + 1) = (Double)(object)values[1 + index];
+ *(basePtr + 0) = (double)(object)values[0 + index];
+ *(basePtr + 1) = (double)(object)values[1 + index];
}
}
}
@@ -632,11 +636,11 @@ namespace System.Numerics
internal unsafe Vector(void* dataPointer, int offset)
: this()
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* castedPtr = (Byte*)dataPointer;
+ byte* castedPtr = (byte*)dataPointer;
castedPtr += offset;
- fixed (Byte* registerBase = &this.register.byte_0)
+ fixed (byte* registerBase = &this.register.byte_0)
{
for (int g = 0; g < Count; g++)
{
@@ -644,11 +648,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* castedPtr = (SByte*)dataPointer;
+ sbyte* castedPtr = (sbyte*)dataPointer;
castedPtr += offset;
- fixed (SByte* registerBase = &this.register.sbyte_0)
+ fixed (sbyte* registerBase = &this.register.sbyte_0)
{
for (int g = 0; g < Count; g++)
{
@@ -656,11 +660,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* castedPtr = (UInt16*)dataPointer;
+ ushort* castedPtr = (ushort*)dataPointer;
castedPtr += offset;
- fixed (UInt16* registerBase = &this.register.uint16_0)
+ fixed (ushort* registerBase = &this.register.uint16_0)
{
for (int g = 0; g < Count; g++)
{
@@ -668,11 +672,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* castedPtr = (Int16*)dataPointer;
+ short* castedPtr = (short*)dataPointer;
castedPtr += offset;
- fixed (Int16* registerBase = &this.register.int16_0)
+ fixed (short* registerBase = &this.register.int16_0)
{
for (int g = 0; g < Count; g++)
{
@@ -680,11 +684,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* castedPtr = (UInt32*)dataPointer;
+ uint* castedPtr = (uint*)dataPointer;
castedPtr += offset;
- fixed (UInt32* registerBase = &this.register.uint32_0)
+ fixed (uint* registerBase = &this.register.uint32_0)
{
for (int g = 0; g < Count; g++)
{
@@ -692,11 +696,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* castedPtr = (Int32*)dataPointer;
+ int* castedPtr = (int*)dataPointer;
castedPtr += offset;
- fixed (Int32* registerBase = &this.register.int32_0)
+ fixed (int* registerBase = &this.register.int32_0)
{
for (int g = 0; g < Count; g++)
{
@@ -704,11 +708,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* castedPtr = (UInt64*)dataPointer;
+ ulong* castedPtr = (ulong*)dataPointer;
castedPtr += offset;
- fixed (UInt64* registerBase = &this.register.uint64_0)
+ fixed (ulong* registerBase = &this.register.uint64_0)
{
for (int g = 0; g < Count; g++)
{
@@ -716,11 +720,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* castedPtr = (Int64*)dataPointer;
+ long* castedPtr = (long*)dataPointer;
castedPtr += offset;
- fixed (Int64* registerBase = &this.register.int64_0)
+ fixed (long* registerBase = &this.register.int64_0)
{
for (int g = 0; g < Count; g++)
{
@@ -728,11 +732,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* castedPtr = (Single*)dataPointer;
+ float* castedPtr = (float*)dataPointer;
castedPtr += offset;
- fixed (Single* registerBase = &this.register.single_0)
+ fixed (float* registerBase = &this.register.single_0)
{
for (int g = 0; g < Count; g++)
{
@@ -740,11 +744,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* castedPtr = (Double*)dataPointer;
+ double* castedPtr = (double*)dataPointer;
castedPtr += offset;
- fixed (Double* registerBase = &this.register.double_0)
+ fixed (double* registerBase = &this.register.double_0)
{
for (int g = 0; g < Count; g++)
{
@@ -763,6 +767,37 @@ namespace System.Numerics
{
this.register = existingRegister;
}
+
+#if netcoreapp
+ /// <summary>
+ /// Constructs a vector from the given span. The span must contain at least Vector'T.Count elements.
+ /// </summary>
+ public Vector(Span<T> values)
+ : this()
+ {
+ if ((typeof(T) == typeof(byte))
+ || (typeof(T) == typeof(sbyte))
+ || (typeof(T) == typeof(ushort))
+ || (typeof(T) == typeof(short))
+ || (typeof(T) == typeof(uint))
+ || (typeof(T) == typeof(int))
+ || (typeof(T) == typeof(ulong))
+ || (typeof(T) == typeof(long))
+ || (typeof(T) == typeof(float))
+ || (typeof(T) == typeof(double)))
+ {
+ if (values.Length < Count)
+ {
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
+ }
+ this = Unsafe.ReadUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)));
+ }
+ else
+ {
+ throw new NotSupportedException(SR.Arg_TypeNotSupported);
+ }
+ }
+#endif
#endregion Constructors
#region Public Instance Methods
@@ -805,123 +840,123 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte[] byteArray = (Byte[])(object)destination;
- fixed (Byte* destinationBase = byteArray)
+ byte[] byteArray = (byte[])(object)destination;
+ fixed (byte* destinationBase = byteArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Byte)(object)this[g];
+ destinationBase[startIndex + g] = (byte)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte[] sbyteArray = (SByte[])(object)destination;
- fixed (SByte* destinationBase = sbyteArray)
+ sbyte[] sbyteArray = (sbyte[])(object)destination;
+ fixed (sbyte* destinationBase = sbyteArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (SByte)(object)this[g];
+ destinationBase[startIndex + g] = (sbyte)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16[] uint16Array = (UInt16[])(object)destination;
- fixed (UInt16* destinationBase = uint16Array)
+ ushort[] uint16Array = (ushort[])(object)destination;
+ fixed (ushort* destinationBase = uint16Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (UInt16)(object)this[g];
+ destinationBase[startIndex + g] = (ushort)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16[] int16Array = (Int16[])(object)destination;
- fixed (Int16* destinationBase = int16Array)
+ short[] int16Array = (short[])(object)destination;
+ fixed (short* destinationBase = int16Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Int16)(object)this[g];
+ destinationBase[startIndex + g] = (short)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32[] uint32Array = (UInt32[])(object)destination;
- fixed (UInt32* destinationBase = uint32Array)
+ uint[] uint32Array = (uint[])(object)destination;
+ fixed (uint* destinationBase = uint32Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (UInt32)(object)this[g];
+ destinationBase[startIndex + g] = (uint)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32[] int32Array = (Int32[])(object)destination;
- fixed (Int32* destinationBase = int32Array)
+ int[] int32Array = (int[])(object)destination;
+ fixed (int* destinationBase = int32Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Int32)(object)this[g];
+ destinationBase[startIndex + g] = (int)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64[] uint64Array = (UInt64[])(object)destination;
- fixed (UInt64* destinationBase = uint64Array)
+ ulong[] uint64Array = (ulong[])(object)destination;
+ fixed (ulong* destinationBase = uint64Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (UInt64)(object)this[g];
+ destinationBase[startIndex + g] = (ulong)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64[] int64Array = (Int64[])(object)destination;
- fixed (Int64* destinationBase = int64Array)
+ long[] int64Array = (long[])(object)destination;
+ fixed (long* destinationBase = int64Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Int64)(object)this[g];
+ destinationBase[startIndex + g] = (long)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single[] singleArray = (Single[])(object)destination;
- fixed (Single* destinationBase = singleArray)
+ float[] singleArray = (float[])(object)destination;
+ fixed (float* destinationBase = singleArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Single)(object)this[g];
+ destinationBase[startIndex + g] = (float)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double[] doubleArray = (Double[])(object)destination;
- fixed (Double* destinationBase = doubleArray)
+ double[] doubleArray = (double[])(object)destination;
+ fixed (double* destinationBase = doubleArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Double)(object)this[g];
+ destinationBase[startIndex + g] = (double)(object)this[g];
}
}
}
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte[] byteArray = (Byte[])(object)destination;
- fixed (Byte* destinationBase = byteArray)
+ byte[] byteArray = (byte[])(object)destination;
+ fixed (byte* destinationBase = byteArray)
{
destinationBase[startIndex + 0] = this.register.byte_0;
destinationBase[startIndex + 1] = this.register.byte_1;
@@ -941,10 +976,10 @@ namespace System.Numerics
destinationBase[startIndex + 15] = this.register.byte_15;
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte[] sbyteArray = (SByte[])(object)destination;
- fixed (SByte* destinationBase = sbyteArray)
+ sbyte[] sbyteArray = (sbyte[])(object)destination;
+ fixed (sbyte* destinationBase = sbyteArray)
{
destinationBase[startIndex + 0] = this.register.sbyte_0;
destinationBase[startIndex + 1] = this.register.sbyte_1;
@@ -964,10 +999,10 @@ namespace System.Numerics
destinationBase[startIndex + 15] = this.register.sbyte_15;
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16[] uint16Array = (UInt16[])(object)destination;
- fixed (UInt16* destinationBase = uint16Array)
+ ushort[] uint16Array = (ushort[])(object)destination;
+ fixed (ushort* destinationBase = uint16Array)
{
destinationBase[startIndex + 0] = this.register.uint16_0;
destinationBase[startIndex + 1] = this.register.uint16_1;
@@ -979,10 +1014,10 @@ namespace System.Numerics
destinationBase[startIndex + 7] = this.register.uint16_7;
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16[] int16Array = (Int16[])(object)destination;
- fixed (Int16* destinationBase = int16Array)
+ short[] int16Array = (short[])(object)destination;
+ fixed (short* destinationBase = int16Array)
{
destinationBase[startIndex + 0] = this.register.int16_0;
destinationBase[startIndex + 1] = this.register.int16_1;
@@ -994,10 +1029,10 @@ namespace System.Numerics
destinationBase[startIndex + 7] = this.register.int16_7;
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32[] uint32Array = (UInt32[])(object)destination;
- fixed (UInt32* destinationBase = uint32Array)
+ uint[] uint32Array = (uint[])(object)destination;
+ fixed (uint* destinationBase = uint32Array)
{
destinationBase[startIndex + 0] = this.register.uint32_0;
destinationBase[startIndex + 1] = this.register.uint32_1;
@@ -1005,10 +1040,10 @@ namespace System.Numerics
destinationBase[startIndex + 3] = this.register.uint32_3;
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32[] int32Array = (Int32[])(object)destination;
- fixed (Int32* destinationBase = int32Array)
+ int[] int32Array = (int[])(object)destination;
+ fixed (int* destinationBase = int32Array)
{
destinationBase[startIndex + 0] = this.register.int32_0;
destinationBase[startIndex + 1] = this.register.int32_1;
@@ -1016,28 +1051,28 @@ namespace System.Numerics
destinationBase[startIndex + 3] = this.register.int32_3;
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64[] uint64Array = (UInt64[])(object)destination;
- fixed (UInt64* destinationBase = uint64Array)
+ ulong[] uint64Array = (ulong[])(object)destination;
+ fixed (ulong* destinationBase = uint64Array)
{
destinationBase[startIndex + 0] = this.register.uint64_0;
destinationBase[startIndex + 1] = this.register.uint64_1;
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64[] int64Array = (Int64[])(object)destination;
- fixed (Int64* destinationBase = int64Array)
+ long[] int64Array = (long[])(object)destination;
+ fixed (long* destinationBase = int64Array)
{
destinationBase[startIndex + 0] = this.register.int64_0;
destinationBase[startIndex + 1] = this.register.int64_1;
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single[] singleArray = (Single[])(object)destination;
- fixed (Single* destinationBase = singleArray)
+ float[] singleArray = (float[])(object)destination;
+ fixed (float* destinationBase = singleArray)
{
destinationBase[startIndex + 0] = this.register.single_0;
destinationBase[startIndex + 1] = this.register.single_1;
@@ -1045,10 +1080,10 @@ namespace System.Numerics
destinationBase[startIndex + 3] = this.register.single_3;
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double[] doubleArray = (Double[])(object)destination;
- fixed (Double* destinationBase = doubleArray)
+ double[] doubleArray = (double[])(object)destination;
+ fixed (double* destinationBase = doubleArray)
{
destinationBase[startIndex + 0] = this.register.double_0;
destinationBase[startIndex + 1] = this.register.double_1;
@@ -1069,72 +1104,72 @@ namespace System.Numerics
{
throw new IndexOutOfRangeException(SR.Format(SR.Arg_ArgumentOutOfRangeException, index));
}
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
return (T)(object)*(basePtr + index);
}
@@ -1182,7 +1217,7 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
return
this.register.byte_0 == other.register.byte_0
@@ -1202,7 +1237,7 @@ namespace System.Numerics
&& this.register.byte_14 == other.register.byte_14
&& this.register.byte_15 == other.register.byte_15;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
return
this.register.sbyte_0 == other.register.sbyte_0
@@ -1222,7 +1257,7 @@ namespace System.Numerics
&& this.register.sbyte_14 == other.register.sbyte_14
&& this.register.sbyte_15 == other.register.sbyte_15;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
return
this.register.uint16_0 == other.register.uint16_0
@@ -1234,7 +1269,7 @@ namespace System.Numerics
&& this.register.uint16_6 == other.register.uint16_6
&& this.register.uint16_7 == other.register.uint16_7;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
return
this.register.int16_0 == other.register.int16_0
@@ -1246,7 +1281,7 @@ namespace System.Numerics
&& this.register.int16_6 == other.register.int16_6
&& this.register.int16_7 == other.register.int16_7;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
return
this.register.uint32_0 == other.register.uint32_0
@@ -1254,7 +1289,7 @@ namespace System.Numerics
&& this.register.uint32_2 == other.register.uint32_2
&& this.register.uint32_3 == other.register.uint32_3;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
return
this.register.int32_0 == other.register.int32_0
@@ -1262,19 +1297,19 @@ namespace System.Numerics
&& this.register.int32_2 == other.register.int32_2
&& this.register.int32_3 == other.register.int32_3;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
return
this.register.uint64_0 == other.register.uint64_0
&& this.register.uint64_1 == other.register.uint64_1;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
return
this.register.int64_0 == other.register.int64_0
&& this.register.int64_1 == other.register.int64_1;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
return
this.register.single_0 == other.register.single_0
@@ -1282,7 +1317,7 @@ namespace System.Numerics
&& this.register.single_2 == other.register.single_2
&& this.register.single_3 == other.register.single_3;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
return
this.register.double_0 == other.register.double_0
@@ -1305,83 +1340,83 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Byte)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((byte)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((SByte)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((sbyte)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((UInt16)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((ushort)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Int16)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((short)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((UInt32)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((uint)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Int32)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((int)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((UInt64)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((ulong)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Int64)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((long)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Single)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((float)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Double)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((double)(object)this[g]).GetHashCode());
}
return hash;
}
@@ -1392,7 +1427,7 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
hash = HashHelpers.Combine(hash, this.register.byte_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.byte_1.GetHashCode());
@@ -1412,7 +1447,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.byte_15.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
hash = HashHelpers.Combine(hash, this.register.sbyte_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.sbyte_1.GetHashCode());
@@ -1432,7 +1467,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.sbyte_15.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
hash = HashHelpers.Combine(hash, this.register.uint16_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.uint16_1.GetHashCode());
@@ -1444,7 +1479,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.uint16_7.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
hash = HashHelpers.Combine(hash, this.register.int16_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.int16_1.GetHashCode());
@@ -1456,7 +1491,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.int16_7.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
hash = HashHelpers.Combine(hash, this.register.uint32_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.uint32_1.GetHashCode());
@@ -1464,7 +1499,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.uint32_3.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
hash = HashHelpers.Combine(hash, this.register.int32_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.int32_1.GetHashCode());
@@ -1472,19 +1507,19 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.int32_3.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
hash = HashHelpers.Combine(hash, this.register.uint64_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.uint64_1.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
hash = HashHelpers.Combine(hash, this.register.int64_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.int64_1.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
hash = HashHelpers.Combine(hash, this.register.single_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.single_1.GetHashCode());
@@ -1492,7 +1527,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.single_3.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
hash = HashHelpers.Combine(hash, this.register.double_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.double_1.GetHashCode());
@@ -1562,93 +1597,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -1660,101 +1695,101 @@ namespace System.Numerics
else
{
Vector<T> sum = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- sum.register.byte_0 = (Byte)(left.register.byte_0 + right.register.byte_0);
- sum.register.byte_1 = (Byte)(left.register.byte_1 + right.register.byte_1);
- sum.register.byte_2 = (Byte)(left.register.byte_2 + right.register.byte_2);
- sum.register.byte_3 = (Byte)(left.register.byte_3 + right.register.byte_3);
- sum.register.byte_4 = (Byte)(left.register.byte_4 + right.register.byte_4);
- sum.register.byte_5 = (Byte)(left.register.byte_5 + right.register.byte_5);
- sum.register.byte_6 = (Byte)(left.register.byte_6 + right.register.byte_6);
- sum.register.byte_7 = (Byte)(left.register.byte_7 + right.register.byte_7);
- sum.register.byte_8 = (Byte)(left.register.byte_8 + right.register.byte_8);
- sum.register.byte_9 = (Byte)(left.register.byte_9 + right.register.byte_9);
- sum.register.byte_10 = (Byte)(left.register.byte_10 + right.register.byte_10);
- sum.register.byte_11 = (Byte)(left.register.byte_11 + right.register.byte_11);
- sum.register.byte_12 = (Byte)(left.register.byte_12 + right.register.byte_12);
- sum.register.byte_13 = (Byte)(left.register.byte_13 + right.register.byte_13);
- sum.register.byte_14 = (Byte)(left.register.byte_14 + right.register.byte_14);
- sum.register.byte_15 = (Byte)(left.register.byte_15 + right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- sum.register.sbyte_0 = (SByte)(left.register.sbyte_0 + right.register.sbyte_0);
- sum.register.sbyte_1 = (SByte)(left.register.sbyte_1 + right.register.sbyte_1);
- sum.register.sbyte_2 = (SByte)(left.register.sbyte_2 + right.register.sbyte_2);
- sum.register.sbyte_3 = (SByte)(left.register.sbyte_3 + right.register.sbyte_3);
- sum.register.sbyte_4 = (SByte)(left.register.sbyte_4 + right.register.sbyte_4);
- sum.register.sbyte_5 = (SByte)(left.register.sbyte_5 + right.register.sbyte_5);
- sum.register.sbyte_6 = (SByte)(left.register.sbyte_6 + right.register.sbyte_6);
- sum.register.sbyte_7 = (SByte)(left.register.sbyte_7 + right.register.sbyte_7);
- sum.register.sbyte_8 = (SByte)(left.register.sbyte_8 + right.register.sbyte_8);
- sum.register.sbyte_9 = (SByte)(left.register.sbyte_9 + right.register.sbyte_9);
- sum.register.sbyte_10 = (SByte)(left.register.sbyte_10 + right.register.sbyte_10);
- sum.register.sbyte_11 = (SByte)(left.register.sbyte_11 + right.register.sbyte_11);
- sum.register.sbyte_12 = (SByte)(left.register.sbyte_12 + right.register.sbyte_12);
- sum.register.sbyte_13 = (SByte)(left.register.sbyte_13 + right.register.sbyte_13);
- sum.register.sbyte_14 = (SByte)(left.register.sbyte_14 + right.register.sbyte_14);
- sum.register.sbyte_15 = (SByte)(left.register.sbyte_15 + right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- sum.register.uint16_0 = (UInt16)(left.register.uint16_0 + right.register.uint16_0);
- sum.register.uint16_1 = (UInt16)(left.register.uint16_1 + right.register.uint16_1);
- sum.register.uint16_2 = (UInt16)(left.register.uint16_2 + right.register.uint16_2);
- sum.register.uint16_3 = (UInt16)(left.register.uint16_3 + right.register.uint16_3);
- sum.register.uint16_4 = (UInt16)(left.register.uint16_4 + right.register.uint16_4);
- sum.register.uint16_5 = (UInt16)(left.register.uint16_5 + right.register.uint16_5);
- sum.register.uint16_6 = (UInt16)(left.register.uint16_6 + right.register.uint16_6);
- sum.register.uint16_7 = (UInt16)(left.register.uint16_7 + right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- sum.register.int16_0 = (Int16)(left.register.int16_0 + right.register.int16_0);
- sum.register.int16_1 = (Int16)(left.register.int16_1 + right.register.int16_1);
- sum.register.int16_2 = (Int16)(left.register.int16_2 + right.register.int16_2);
- sum.register.int16_3 = (Int16)(left.register.int16_3 + right.register.int16_3);
- sum.register.int16_4 = (Int16)(left.register.int16_4 + right.register.int16_4);
- sum.register.int16_5 = (Int16)(left.register.int16_5 + right.register.int16_5);
- sum.register.int16_6 = (Int16)(left.register.int16_6 + right.register.int16_6);
- sum.register.int16_7 = (Int16)(left.register.int16_7 + right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- sum.register.uint32_0 = (UInt32)(left.register.uint32_0 + right.register.uint32_0);
- sum.register.uint32_1 = (UInt32)(left.register.uint32_1 + right.register.uint32_1);
- sum.register.uint32_2 = (UInt32)(left.register.uint32_2 + right.register.uint32_2);
- sum.register.uint32_3 = (UInt32)(left.register.uint32_3 + right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- sum.register.int32_0 = (Int32)(left.register.int32_0 + right.register.int32_0);
- sum.register.int32_1 = (Int32)(left.register.int32_1 + right.register.int32_1);
- sum.register.int32_2 = (Int32)(left.register.int32_2 + right.register.int32_2);
- sum.register.int32_3 = (Int32)(left.register.int32_3 + right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- sum.register.uint64_0 = (UInt64)(left.register.uint64_0 + right.register.uint64_0);
- sum.register.uint64_1 = (UInt64)(left.register.uint64_1 + right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- sum.register.int64_0 = (Int64)(left.register.int64_0 + right.register.int64_0);
- sum.register.int64_1 = (Int64)(left.register.int64_1 + right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- sum.register.single_0 = (Single)(left.register.single_0 + right.register.single_0);
- sum.register.single_1 = (Single)(left.register.single_1 + right.register.single_1);
- sum.register.single_2 = (Single)(left.register.single_2 + right.register.single_2);
- sum.register.single_3 = (Single)(left.register.single_3 + right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- sum.register.double_0 = (Double)(left.register.double_0 + right.register.double_0);
- sum.register.double_1 = (Double)(left.register.double_1 + right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ sum.register.byte_0 = (byte)(left.register.byte_0 + right.register.byte_0);
+ sum.register.byte_1 = (byte)(left.register.byte_1 + right.register.byte_1);
+ sum.register.byte_2 = (byte)(left.register.byte_2 + right.register.byte_2);
+ sum.register.byte_3 = (byte)(left.register.byte_3 + right.register.byte_3);
+ sum.register.byte_4 = (byte)(left.register.byte_4 + right.register.byte_4);
+ sum.register.byte_5 = (byte)(left.register.byte_5 + right.register.byte_5);
+ sum.register.byte_6 = (byte)(left.register.byte_6 + right.register.byte_6);
+ sum.register.byte_7 = (byte)(left.register.byte_7 + right.register.byte_7);
+ sum.register.byte_8 = (byte)(left.register.byte_8 + right.register.byte_8);
+ sum.register.byte_9 = (byte)(left.register.byte_9 + right.register.byte_9);
+ sum.register.byte_10 = (byte)(left.register.byte_10 + right.register.byte_10);
+ sum.register.byte_11 = (byte)(left.register.byte_11 + right.register.byte_11);
+ sum.register.byte_12 = (byte)(left.register.byte_12 + right.register.byte_12);
+ sum.register.byte_13 = (byte)(left.register.byte_13 + right.register.byte_13);
+ sum.register.byte_14 = (byte)(left.register.byte_14 + right.register.byte_14);
+ sum.register.byte_15 = (byte)(left.register.byte_15 + right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ sum.register.sbyte_0 = (sbyte)(left.register.sbyte_0 + right.register.sbyte_0);
+ sum.register.sbyte_1 = (sbyte)(left.register.sbyte_1 + right.register.sbyte_1);
+ sum.register.sbyte_2 = (sbyte)(left.register.sbyte_2 + right.register.sbyte_2);
+ sum.register.sbyte_3 = (sbyte)(left.register.sbyte_3 + right.register.sbyte_3);
+ sum.register.sbyte_4 = (sbyte)(left.register.sbyte_4 + right.register.sbyte_4);
+ sum.register.sbyte_5 = (sbyte)(left.register.sbyte_5 + right.register.sbyte_5);
+ sum.register.sbyte_6 = (sbyte)(left.register.sbyte_6 + right.register.sbyte_6);
+ sum.register.sbyte_7 = (sbyte)(left.register.sbyte_7 + right.register.sbyte_7);
+ sum.register.sbyte_8 = (sbyte)(left.register.sbyte_8 + right.register.sbyte_8);
+ sum.register.sbyte_9 = (sbyte)(left.register.sbyte_9 + right.register.sbyte_9);
+ sum.register.sbyte_10 = (sbyte)(left.register.sbyte_10 + right.register.sbyte_10);
+ sum.register.sbyte_11 = (sbyte)(left.register.sbyte_11 + right.register.sbyte_11);
+ sum.register.sbyte_12 = (sbyte)(left.register.sbyte_12 + right.register.sbyte_12);
+ sum.register.sbyte_13 = (sbyte)(left.register.sbyte_13 + right.register.sbyte_13);
+ sum.register.sbyte_14 = (sbyte)(left.register.sbyte_14 + right.register.sbyte_14);
+ sum.register.sbyte_15 = (sbyte)(left.register.sbyte_15 + right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ sum.register.uint16_0 = (ushort)(left.register.uint16_0 + right.register.uint16_0);
+ sum.register.uint16_1 = (ushort)(left.register.uint16_1 + right.register.uint16_1);
+ sum.register.uint16_2 = (ushort)(left.register.uint16_2 + right.register.uint16_2);
+ sum.register.uint16_3 = (ushort)(left.register.uint16_3 + right.register.uint16_3);
+ sum.register.uint16_4 = (ushort)(left.register.uint16_4 + right.register.uint16_4);
+ sum.register.uint16_5 = (ushort)(left.register.uint16_5 + right.register.uint16_5);
+ sum.register.uint16_6 = (ushort)(left.register.uint16_6 + right.register.uint16_6);
+ sum.register.uint16_7 = (ushort)(left.register.uint16_7 + right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ sum.register.int16_0 = (short)(left.register.int16_0 + right.register.int16_0);
+ sum.register.int16_1 = (short)(left.register.int16_1 + right.register.int16_1);
+ sum.register.int16_2 = (short)(left.register.int16_2 + right.register.int16_2);
+ sum.register.int16_3 = (short)(left.register.int16_3 + right.register.int16_3);
+ sum.register.int16_4 = (short)(left.register.int16_4 + right.register.int16_4);
+ sum.register.int16_5 = (short)(left.register.int16_5 + right.register.int16_5);
+ sum.register.int16_6 = (short)(left.register.int16_6 + right.register.int16_6);
+ sum.register.int16_7 = (short)(left.register.int16_7 + right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ sum.register.uint32_0 = (uint)(left.register.uint32_0 + right.register.uint32_0);
+ sum.register.uint32_1 = (uint)(left.register.uint32_1 + right.register.uint32_1);
+ sum.register.uint32_2 = (uint)(left.register.uint32_2 + right.register.uint32_2);
+ sum.register.uint32_3 = (uint)(left.register.uint32_3 + right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ sum.register.int32_0 = (int)(left.register.int32_0 + right.register.int32_0);
+ sum.register.int32_1 = (int)(left.register.int32_1 + right.register.int32_1);
+ sum.register.int32_2 = (int)(left.register.int32_2 + right.register.int32_2);
+ sum.register.int32_3 = (int)(left.register.int32_3 + right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ sum.register.uint64_0 = (ulong)(left.register.uint64_0 + right.register.uint64_0);
+ sum.register.uint64_1 = (ulong)(left.register.uint64_1 + right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ sum.register.int64_0 = (long)(left.register.int64_0 + right.register.int64_0);
+ sum.register.int64_1 = (long)(left.register.int64_1 + right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ sum.register.single_0 = (float)(left.register.single_0 + right.register.single_0);
+ sum.register.single_1 = (float)(left.register.single_1 + right.register.single_1);
+ sum.register.single_2 = (float)(left.register.single_2 + right.register.single_2);
+ sum.register.single_3 = (float)(left.register.single_3 + right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ sum.register.double_0 = (double)(left.register.double_0 + right.register.double_0);
+ sum.register.double_1 = (double)(left.register.double_1 + right.register.double_1);
}
return sum;
}
@@ -1773,93 +1808,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -1871,101 +1906,101 @@ namespace System.Numerics
else
{
Vector<T> difference = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- difference.register.byte_0 = (Byte)(left.register.byte_0 - right.register.byte_0);
- difference.register.byte_1 = (Byte)(left.register.byte_1 - right.register.byte_1);
- difference.register.byte_2 = (Byte)(left.register.byte_2 - right.register.byte_2);
- difference.register.byte_3 = (Byte)(left.register.byte_3 - right.register.byte_3);
- difference.register.byte_4 = (Byte)(left.register.byte_4 - right.register.byte_4);
- difference.register.byte_5 = (Byte)(left.register.byte_5 - right.register.byte_5);
- difference.register.byte_6 = (Byte)(left.register.byte_6 - right.register.byte_6);
- difference.register.byte_7 = (Byte)(left.register.byte_7 - right.register.byte_7);
- difference.register.byte_8 = (Byte)(left.register.byte_8 - right.register.byte_8);
- difference.register.byte_9 = (Byte)(left.register.byte_9 - right.register.byte_9);
- difference.register.byte_10 = (Byte)(left.register.byte_10 - right.register.byte_10);
- difference.register.byte_11 = (Byte)(left.register.byte_11 - right.register.byte_11);
- difference.register.byte_12 = (Byte)(left.register.byte_12 - right.register.byte_12);
- difference.register.byte_13 = (Byte)(left.register.byte_13 - right.register.byte_13);
- difference.register.byte_14 = (Byte)(left.register.byte_14 - right.register.byte_14);
- difference.register.byte_15 = (Byte)(left.register.byte_15 - right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- difference.register.sbyte_0 = (SByte)(left.register.sbyte_0 - right.register.sbyte_0);
- difference.register.sbyte_1 = (SByte)(left.register.sbyte_1 - right.register.sbyte_1);
- difference.register.sbyte_2 = (SByte)(left.register.sbyte_2 - right.register.sbyte_2);
- difference.register.sbyte_3 = (SByte)(left.register.sbyte_3 - right.register.sbyte_3);
- difference.register.sbyte_4 = (SByte)(left.register.sbyte_4 - right.register.sbyte_4);
- difference.register.sbyte_5 = (SByte)(left.register.sbyte_5 - right.register.sbyte_5);
- difference.register.sbyte_6 = (SByte)(left.register.sbyte_6 - right.register.sbyte_6);
- difference.register.sbyte_7 = (SByte)(left.register.sbyte_7 - right.register.sbyte_7);
- difference.register.sbyte_8 = (SByte)(left.register.sbyte_8 - right.register.sbyte_8);
- difference.register.sbyte_9 = (SByte)(left.register.sbyte_9 - right.register.sbyte_9);
- difference.register.sbyte_10 = (SByte)(left.register.sbyte_10 - right.register.sbyte_10);
- difference.register.sbyte_11 = (SByte)(left.register.sbyte_11 - right.register.sbyte_11);
- difference.register.sbyte_12 = (SByte)(left.register.sbyte_12 - right.register.sbyte_12);
- difference.register.sbyte_13 = (SByte)(left.register.sbyte_13 - right.register.sbyte_13);
- difference.register.sbyte_14 = (SByte)(left.register.sbyte_14 - right.register.sbyte_14);
- difference.register.sbyte_15 = (SByte)(left.register.sbyte_15 - right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- difference.register.uint16_0 = (UInt16)(left.register.uint16_0 - right.register.uint16_0);
- difference.register.uint16_1 = (UInt16)(left.register.uint16_1 - right.register.uint16_1);
- difference.register.uint16_2 = (UInt16)(left.register.uint16_2 - right.register.uint16_2);
- difference.register.uint16_3 = (UInt16)(left.register.uint16_3 - right.register.uint16_3);
- difference.register.uint16_4 = (UInt16)(left.register.uint16_4 - right.register.uint16_4);
- difference.register.uint16_5 = (UInt16)(left.register.uint16_5 - right.register.uint16_5);
- difference.register.uint16_6 = (UInt16)(left.register.uint16_6 - right.register.uint16_6);
- difference.register.uint16_7 = (UInt16)(left.register.uint16_7 - right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- difference.register.int16_0 = (Int16)(left.register.int16_0 - right.register.int16_0);
- difference.register.int16_1 = (Int16)(left.register.int16_1 - right.register.int16_1);
- difference.register.int16_2 = (Int16)(left.register.int16_2 - right.register.int16_2);
- difference.register.int16_3 = (Int16)(left.register.int16_3 - right.register.int16_3);
- difference.register.int16_4 = (Int16)(left.register.int16_4 - right.register.int16_4);
- difference.register.int16_5 = (Int16)(left.register.int16_5 - right.register.int16_5);
- difference.register.int16_6 = (Int16)(left.register.int16_6 - right.register.int16_6);
- difference.register.int16_7 = (Int16)(left.register.int16_7 - right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- difference.register.uint32_0 = (UInt32)(left.register.uint32_0 - right.register.uint32_0);
- difference.register.uint32_1 = (UInt32)(left.register.uint32_1 - right.register.uint32_1);
- difference.register.uint32_2 = (UInt32)(left.register.uint32_2 - right.register.uint32_2);
- difference.register.uint32_3 = (UInt32)(left.register.uint32_3 - right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- difference.register.int32_0 = (Int32)(left.register.int32_0 - right.register.int32_0);
- difference.register.int32_1 = (Int32)(left.register.int32_1 - right.register.int32_1);
- difference.register.int32_2 = (Int32)(left.register.int32_2 - right.register.int32_2);
- difference.register.int32_3 = (Int32)(left.register.int32_3 - right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- difference.register.uint64_0 = (UInt64)(left.register.uint64_0 - right.register.uint64_0);
- difference.register.uint64_1 = (UInt64)(left.register.uint64_1 - right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- difference.register.int64_0 = (Int64)(left.register.int64_0 - right.register.int64_0);
- difference.register.int64_1 = (Int64)(left.register.int64_1 - right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- difference.register.single_0 = (Single)(left.register.single_0 - right.register.single_0);
- difference.register.single_1 = (Single)(left.register.single_1 - right.register.single_1);
- difference.register.single_2 = (Single)(left.register.single_2 - right.register.single_2);
- difference.register.single_3 = (Single)(left.register.single_3 - right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- difference.register.double_0 = (Double)(left.register.double_0 - right.register.double_0);
- difference.register.double_1 = (Double)(left.register.double_1 - right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ difference.register.byte_0 = (byte)(left.register.byte_0 - right.register.byte_0);
+ difference.register.byte_1 = (byte)(left.register.byte_1 - right.register.byte_1);
+ difference.register.byte_2 = (byte)(left.register.byte_2 - right.register.byte_2);
+ difference.register.byte_3 = (byte)(left.register.byte_3 - right.register.byte_3);
+ difference.register.byte_4 = (byte)(left.register.byte_4 - right.register.byte_4);
+ difference.register.byte_5 = (byte)(left.register.byte_5 - right.register.byte_5);
+ difference.register.byte_6 = (byte)(left.register.byte_6 - right.register.byte_6);
+ difference.register.byte_7 = (byte)(left.register.byte_7 - right.register.byte_7);
+ difference.register.byte_8 = (byte)(left.register.byte_8 - right.register.byte_8);
+ difference.register.byte_9 = (byte)(left.register.byte_9 - right.register.byte_9);
+ difference.register.byte_10 = (byte)(left.register.byte_10 - right.register.byte_10);
+ difference.register.byte_11 = (byte)(left.register.byte_11 - right.register.byte_11);
+ difference.register.byte_12 = (byte)(left.register.byte_12 - right.register.byte_12);
+ difference.register.byte_13 = (byte)(left.register.byte_13 - right.register.byte_13);
+ difference.register.byte_14 = (byte)(left.register.byte_14 - right.register.byte_14);
+ difference.register.byte_15 = (byte)(left.register.byte_15 - right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ difference.register.sbyte_0 = (sbyte)(left.register.sbyte_0 - right.register.sbyte_0);
+ difference.register.sbyte_1 = (sbyte)(left.register.sbyte_1 - right.register.sbyte_1);
+ difference.register.sbyte_2 = (sbyte)(left.register.sbyte_2 - right.register.sbyte_2);
+ difference.register.sbyte_3 = (sbyte)(left.register.sbyte_3 - right.register.sbyte_3);
+ difference.register.sbyte_4 = (sbyte)(left.register.sbyte_4 - right.register.sbyte_4);
+ difference.register.sbyte_5 = (sbyte)(left.register.sbyte_5 - right.register.sbyte_5);
+ difference.register.sbyte_6 = (sbyte)(left.register.sbyte_6 - right.register.sbyte_6);
+ difference.register.sbyte_7 = (sbyte)(left.register.sbyte_7 - right.register.sbyte_7);
+ difference.register.sbyte_8 = (sbyte)(left.register.sbyte_8 - right.register.sbyte_8);
+ difference.register.sbyte_9 = (sbyte)(left.register.sbyte_9 - right.register.sbyte_9);
+ difference.register.sbyte_10 = (sbyte)(left.register.sbyte_10 - right.register.sbyte_10);
+ difference.register.sbyte_11 = (sbyte)(left.register.sbyte_11 - right.register.sbyte_11);
+ difference.register.sbyte_12 = (sbyte)(left.register.sbyte_12 - right.register.sbyte_12);
+ difference.register.sbyte_13 = (sbyte)(left.register.sbyte_13 - right.register.sbyte_13);
+ difference.register.sbyte_14 = (sbyte)(left.register.sbyte_14 - right.register.sbyte_14);
+ difference.register.sbyte_15 = (sbyte)(left.register.sbyte_15 - right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ difference.register.uint16_0 = (ushort)(left.register.uint16_0 - right.register.uint16_0);
+ difference.register.uint16_1 = (ushort)(left.register.uint16_1 - right.register.uint16_1);
+ difference.register.uint16_2 = (ushort)(left.register.uint16_2 - right.register.uint16_2);
+ difference.register.uint16_3 = (ushort)(left.register.uint16_3 - right.register.uint16_3);
+ difference.register.uint16_4 = (ushort)(left.register.uint16_4 - right.register.uint16_4);
+ difference.register.uint16_5 = (ushort)(left.register.uint16_5 - right.register.uint16_5);
+ difference.register.uint16_6 = (ushort)(left.register.uint16_6 - right.register.uint16_6);
+ difference.register.uint16_7 = (ushort)(left.register.uint16_7 - right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ difference.register.int16_0 = (short)(left.register.int16_0 - right.register.int16_0);
+ difference.register.int16_1 = (short)(left.register.int16_1 - right.register.int16_1);
+ difference.register.int16_2 = (short)(left.register.int16_2 - right.register.int16_2);
+ difference.register.int16_3 = (short)(left.register.int16_3 - right.register.int16_3);
+ difference.register.int16_4 = (short)(left.register.int16_4 - right.register.int16_4);
+ difference.register.int16_5 = (short)(left.register.int16_5 - right.register.int16_5);
+ difference.register.int16_6 = (short)(left.register.int16_6 - right.register.int16_6);
+ difference.register.int16_7 = (short)(left.register.int16_7 - right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ difference.register.uint32_0 = (uint)(left.register.uint32_0 - right.register.uint32_0);
+ difference.register.uint32_1 = (uint)(left.register.uint32_1 - right.register.uint32_1);
+ difference.register.uint32_2 = (uint)(left.register.uint32_2 - right.register.uint32_2);
+ difference.register.uint32_3 = (uint)(left.register.uint32_3 - right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ difference.register.int32_0 = (int)(left.register.int32_0 - right.register.int32_0);
+ difference.register.int32_1 = (int)(left.register.int32_1 - right.register.int32_1);
+ difference.register.int32_2 = (int)(left.register.int32_2 - right.register.int32_2);
+ difference.register.int32_3 = (int)(left.register.int32_3 - right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ difference.register.uint64_0 = (ulong)(left.register.uint64_0 - right.register.uint64_0);
+ difference.register.uint64_1 = (ulong)(left.register.uint64_1 - right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ difference.register.int64_0 = (long)(left.register.int64_0 - right.register.int64_0);
+ difference.register.int64_1 = (long)(left.register.int64_1 - right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ difference.register.single_0 = (float)(left.register.single_0 - right.register.single_0);
+ difference.register.single_1 = (float)(left.register.single_1 - right.register.single_1);
+ difference.register.single_2 = (float)(left.register.single_2 - right.register.single_2);
+ difference.register.single_3 = (float)(left.register.single_3 - right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ difference.register.double_0 = (double)(left.register.double_0 - right.register.double_0);
+ difference.register.double_1 = (double)(left.register.double_1 - right.register.double_1);
}
return difference;
}
@@ -1985,93 +2020,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -2083,101 +2118,101 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- product.register.byte_0 = (Byte)(left.register.byte_0 * right.register.byte_0);
- product.register.byte_1 = (Byte)(left.register.byte_1 * right.register.byte_1);
- product.register.byte_2 = (Byte)(left.register.byte_2 * right.register.byte_2);
- product.register.byte_3 = (Byte)(left.register.byte_3 * right.register.byte_3);
- product.register.byte_4 = (Byte)(left.register.byte_4 * right.register.byte_4);
- product.register.byte_5 = (Byte)(left.register.byte_5 * right.register.byte_5);
- product.register.byte_6 = (Byte)(left.register.byte_6 * right.register.byte_6);
- product.register.byte_7 = (Byte)(left.register.byte_7 * right.register.byte_7);
- product.register.byte_8 = (Byte)(left.register.byte_8 * right.register.byte_8);
- product.register.byte_9 = (Byte)(left.register.byte_9 * right.register.byte_9);
- product.register.byte_10 = (Byte)(left.register.byte_10 * right.register.byte_10);
- product.register.byte_11 = (Byte)(left.register.byte_11 * right.register.byte_11);
- product.register.byte_12 = (Byte)(left.register.byte_12 * right.register.byte_12);
- product.register.byte_13 = (Byte)(left.register.byte_13 * right.register.byte_13);
- product.register.byte_14 = (Byte)(left.register.byte_14 * right.register.byte_14);
- product.register.byte_15 = (Byte)(left.register.byte_15 * right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- product.register.sbyte_0 = (SByte)(left.register.sbyte_0 * right.register.sbyte_0);
- product.register.sbyte_1 = (SByte)(left.register.sbyte_1 * right.register.sbyte_1);
- product.register.sbyte_2 = (SByte)(left.register.sbyte_2 * right.register.sbyte_2);
- product.register.sbyte_3 = (SByte)(left.register.sbyte_3 * right.register.sbyte_3);
- product.register.sbyte_4 = (SByte)(left.register.sbyte_4 * right.register.sbyte_4);
- product.register.sbyte_5 = (SByte)(left.register.sbyte_5 * right.register.sbyte_5);
- product.register.sbyte_6 = (SByte)(left.register.sbyte_6 * right.register.sbyte_6);
- product.register.sbyte_7 = (SByte)(left.register.sbyte_7 * right.register.sbyte_7);
- product.register.sbyte_8 = (SByte)(left.register.sbyte_8 * right.register.sbyte_8);
- product.register.sbyte_9 = (SByte)(left.register.sbyte_9 * right.register.sbyte_9);
- product.register.sbyte_10 = (SByte)(left.register.sbyte_10 * right.register.sbyte_10);
- product.register.sbyte_11 = (SByte)(left.register.sbyte_11 * right.register.sbyte_11);
- product.register.sbyte_12 = (SByte)(left.register.sbyte_12 * right.register.sbyte_12);
- product.register.sbyte_13 = (SByte)(left.register.sbyte_13 * right.register.sbyte_13);
- product.register.sbyte_14 = (SByte)(left.register.sbyte_14 * right.register.sbyte_14);
- product.register.sbyte_15 = (SByte)(left.register.sbyte_15 * right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- product.register.uint16_0 = (UInt16)(left.register.uint16_0 * right.register.uint16_0);
- product.register.uint16_1 = (UInt16)(left.register.uint16_1 * right.register.uint16_1);
- product.register.uint16_2 = (UInt16)(left.register.uint16_2 * right.register.uint16_2);
- product.register.uint16_3 = (UInt16)(left.register.uint16_3 * right.register.uint16_3);
- product.register.uint16_4 = (UInt16)(left.register.uint16_4 * right.register.uint16_4);
- product.register.uint16_5 = (UInt16)(left.register.uint16_5 * right.register.uint16_5);
- product.register.uint16_6 = (UInt16)(left.register.uint16_6 * right.register.uint16_6);
- product.register.uint16_7 = (UInt16)(left.register.uint16_7 * right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- product.register.int16_0 = (Int16)(left.register.int16_0 * right.register.int16_0);
- product.register.int16_1 = (Int16)(left.register.int16_1 * right.register.int16_1);
- product.register.int16_2 = (Int16)(left.register.int16_2 * right.register.int16_2);
- product.register.int16_3 = (Int16)(left.register.int16_3 * right.register.int16_3);
- product.register.int16_4 = (Int16)(left.register.int16_4 * right.register.int16_4);
- product.register.int16_5 = (Int16)(left.register.int16_5 * right.register.int16_5);
- product.register.int16_6 = (Int16)(left.register.int16_6 * right.register.int16_6);
- product.register.int16_7 = (Int16)(left.register.int16_7 * right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- product.register.uint32_0 = (UInt32)(left.register.uint32_0 * right.register.uint32_0);
- product.register.uint32_1 = (UInt32)(left.register.uint32_1 * right.register.uint32_1);
- product.register.uint32_2 = (UInt32)(left.register.uint32_2 * right.register.uint32_2);
- product.register.uint32_3 = (UInt32)(left.register.uint32_3 * right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- product.register.int32_0 = (Int32)(left.register.int32_0 * right.register.int32_0);
- product.register.int32_1 = (Int32)(left.register.int32_1 * right.register.int32_1);
- product.register.int32_2 = (Int32)(left.register.int32_2 * right.register.int32_2);
- product.register.int32_3 = (Int32)(left.register.int32_3 * right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- product.register.uint64_0 = (UInt64)(left.register.uint64_0 * right.register.uint64_0);
- product.register.uint64_1 = (UInt64)(left.register.uint64_1 * right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- product.register.int64_0 = (Int64)(left.register.int64_0 * right.register.int64_0);
- product.register.int64_1 = (Int64)(left.register.int64_1 * right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- product.register.single_0 = (Single)(left.register.single_0 * right.register.single_0);
- product.register.single_1 = (Single)(left.register.single_1 * right.register.single_1);
- product.register.single_2 = (Single)(left.register.single_2 * right.register.single_2);
- product.register.single_3 = (Single)(left.register.single_3 * right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- product.register.double_0 = (Double)(left.register.double_0 * right.register.double_0);
- product.register.double_1 = (Double)(left.register.double_1 * right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ product.register.byte_0 = (byte)(left.register.byte_0 * right.register.byte_0);
+ product.register.byte_1 = (byte)(left.register.byte_1 * right.register.byte_1);
+ product.register.byte_2 = (byte)(left.register.byte_2 * right.register.byte_2);
+ product.register.byte_3 = (byte)(left.register.byte_3 * right.register.byte_3);
+ product.register.byte_4 = (byte)(left.register.byte_4 * right.register.byte_4);
+ product.register.byte_5 = (byte)(left.register.byte_5 * right.register.byte_5);
+ product.register.byte_6 = (byte)(left.register.byte_6 * right.register.byte_6);
+ product.register.byte_7 = (byte)(left.register.byte_7 * right.register.byte_7);
+ product.register.byte_8 = (byte)(left.register.byte_8 * right.register.byte_8);
+ product.register.byte_9 = (byte)(left.register.byte_9 * right.register.byte_9);
+ product.register.byte_10 = (byte)(left.register.byte_10 * right.register.byte_10);
+ product.register.byte_11 = (byte)(left.register.byte_11 * right.register.byte_11);
+ product.register.byte_12 = (byte)(left.register.byte_12 * right.register.byte_12);
+ product.register.byte_13 = (byte)(left.register.byte_13 * right.register.byte_13);
+ product.register.byte_14 = (byte)(left.register.byte_14 * right.register.byte_14);
+ product.register.byte_15 = (byte)(left.register.byte_15 * right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ product.register.sbyte_0 = (sbyte)(left.register.sbyte_0 * right.register.sbyte_0);
+ product.register.sbyte_1 = (sbyte)(left.register.sbyte_1 * right.register.sbyte_1);
+ product.register.sbyte_2 = (sbyte)(left.register.sbyte_2 * right.register.sbyte_2);
+ product.register.sbyte_3 = (sbyte)(left.register.sbyte_3 * right.register.sbyte_3);
+ product.register.sbyte_4 = (sbyte)(left.register.sbyte_4 * right.register.sbyte_4);
+ product.register.sbyte_5 = (sbyte)(left.register.sbyte_5 * right.register.sbyte_5);
+ product.register.sbyte_6 = (sbyte)(left.register.sbyte_6 * right.register.sbyte_6);
+ product.register.sbyte_7 = (sbyte)(left.register.sbyte_7 * right.register.sbyte_7);
+ product.register.sbyte_8 = (sbyte)(left.register.sbyte_8 * right.register.sbyte_8);
+ product.register.sbyte_9 = (sbyte)(left.register.sbyte_9 * right.register.sbyte_9);
+ product.register.sbyte_10 = (sbyte)(left.register.sbyte_10 * right.register.sbyte_10);
+ product.register.sbyte_11 = (sbyte)(left.register.sbyte_11 * right.register.sbyte_11);
+ product.register.sbyte_12 = (sbyte)(left.register.sbyte_12 * right.register.sbyte_12);
+ product.register.sbyte_13 = (sbyte)(left.register.sbyte_13 * right.register.sbyte_13);
+ product.register.sbyte_14 = (sbyte)(left.register.sbyte_14 * right.register.sbyte_14);
+ product.register.sbyte_15 = (sbyte)(left.register.sbyte_15 * right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ product.register.uint16_0 = (ushort)(left.register.uint16_0 * right.register.uint16_0);
+ product.register.uint16_1 = (ushort)(left.register.uint16_1 * right.register.uint16_1);
+ product.register.uint16_2 = (ushort)(left.register.uint16_2 * right.register.uint16_2);
+ product.register.uint16_3 = (ushort)(left.register.uint16_3 * right.register.uint16_3);
+ product.register.uint16_4 = (ushort)(left.register.uint16_4 * right.register.uint16_4);
+ product.register.uint16_5 = (ushort)(left.register.uint16_5 * right.register.uint16_5);
+ product.register.uint16_6 = (ushort)(left.register.uint16_6 * right.register.uint16_6);
+ product.register.uint16_7 = (ushort)(left.register.uint16_7 * right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ product.register.int16_0 = (short)(left.register.int16_0 * right.register.int16_0);
+ product.register.int16_1 = (short)(left.register.int16_1 * right.register.int16_1);
+ product.register.int16_2 = (short)(left.register.int16_2 * right.register.int16_2);
+ product.register.int16_3 = (short)(left.register.int16_3 * right.register.int16_3);
+ product.register.int16_4 = (short)(left.register.int16_4 * right.register.int16_4);
+ product.register.int16_5 = (short)(left.register.int16_5 * right.register.int16_5);
+ product.register.int16_6 = (short)(left.register.int16_6 * right.register.int16_6);
+ product.register.int16_7 = (short)(left.register.int16_7 * right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ product.register.uint32_0 = (uint)(left.register.uint32_0 * right.register.uint32_0);
+ product.register.uint32_1 = (uint)(left.register.uint32_1 * right.register.uint32_1);
+ product.register.uint32_2 = (uint)(left.register.uint32_2 * right.register.uint32_2);
+ product.register.uint32_3 = (uint)(left.register.uint32_3 * right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ product.register.int32_0 = (int)(left.register.int32_0 * right.register.int32_0);
+ product.register.int32_1 = (int)(left.register.int32_1 * right.register.int32_1);
+ product.register.int32_2 = (int)(left.register.int32_2 * right.register.int32_2);
+ product.register.int32_3 = (int)(left.register.int32_3 * right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ product.register.uint64_0 = (ulong)(left.register.uint64_0 * right.register.uint64_0);
+ product.register.uint64_1 = (ulong)(left.register.uint64_1 * right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ product.register.int64_0 = (long)(left.register.int64_0 * right.register.int64_0);
+ product.register.int64_1 = (long)(left.register.int64_1 * right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ product.register.single_0 = (float)(left.register.single_0 * right.register.single_0);
+ product.register.single_1 = (float)(left.register.single_1 * right.register.single_1);
+ product.register.single_2 = (float)(left.register.single_2 * right.register.single_2);
+ product.register.single_3 = (float)(left.register.single_3 * right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ product.register.double_0 = (double)(left.register.double_0 * right.register.double_0);
+ product.register.double_1 = (double)(left.register.double_1 * right.register.double_1);
}
return product;
}
@@ -2202,101 +2237,101 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- product.register.byte_0 = (Byte)(value.register.byte_0 * (Byte)(object)factor);
- product.register.byte_1 = (Byte)(value.register.byte_1 * (Byte)(object)factor);
- product.register.byte_2 = (Byte)(value.register.byte_2 * (Byte)(object)factor);
- product.register.byte_3 = (Byte)(value.register.byte_3 * (Byte)(object)factor);
- product.register.byte_4 = (Byte)(value.register.byte_4 * (Byte)(object)factor);
- product.register.byte_5 = (Byte)(value.register.byte_5 * (Byte)(object)factor);
- product.register.byte_6 = (Byte)(value.register.byte_6 * (Byte)(object)factor);
- product.register.byte_7 = (Byte)(value.register.byte_7 * (Byte)(object)factor);
- product.register.byte_8 = (Byte)(value.register.byte_8 * (Byte)(object)factor);
- product.register.byte_9 = (Byte)(value.register.byte_9 * (Byte)(object)factor);
- product.register.byte_10 = (Byte)(value.register.byte_10 * (Byte)(object)factor);
- product.register.byte_11 = (Byte)(value.register.byte_11 * (Byte)(object)factor);
- product.register.byte_12 = (Byte)(value.register.byte_12 * (Byte)(object)factor);
- product.register.byte_13 = (Byte)(value.register.byte_13 * (Byte)(object)factor);
- product.register.byte_14 = (Byte)(value.register.byte_14 * (Byte)(object)factor);
- product.register.byte_15 = (Byte)(value.register.byte_15 * (Byte)(object)factor);
- }
- else if (typeof(T) == typeof(SByte))
- {
- product.register.sbyte_0 = (SByte)(value.register.sbyte_0 * (SByte)(object)factor);
- product.register.sbyte_1 = (SByte)(value.register.sbyte_1 * (SByte)(object)factor);
- product.register.sbyte_2 = (SByte)(value.register.sbyte_2 * (SByte)(object)factor);
- product.register.sbyte_3 = (SByte)(value.register.sbyte_3 * (SByte)(object)factor);
- product.register.sbyte_4 = (SByte)(value.register.sbyte_4 * (SByte)(object)factor);
- product.register.sbyte_5 = (SByte)(value.register.sbyte_5 * (SByte)(object)factor);
- product.register.sbyte_6 = (SByte)(value.register.sbyte_6 * (SByte)(object)factor);
- product.register.sbyte_7 = (SByte)(value.register.sbyte_7 * (SByte)(object)factor);
- product.register.sbyte_8 = (SByte)(value.register.sbyte_8 * (SByte)(object)factor);
- product.register.sbyte_9 = (SByte)(value.register.sbyte_9 * (SByte)(object)factor);
- product.register.sbyte_10 = (SByte)(value.register.sbyte_10 * (SByte)(object)factor);
- product.register.sbyte_11 = (SByte)(value.register.sbyte_11 * (SByte)(object)factor);
- product.register.sbyte_12 = (SByte)(value.register.sbyte_12 * (SByte)(object)factor);
- product.register.sbyte_13 = (SByte)(value.register.sbyte_13 * (SByte)(object)factor);
- product.register.sbyte_14 = (SByte)(value.register.sbyte_14 * (SByte)(object)factor);
- product.register.sbyte_15 = (SByte)(value.register.sbyte_15 * (SByte)(object)factor);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- product.register.uint16_0 = (UInt16)(value.register.uint16_0 * (UInt16)(object)factor);
- product.register.uint16_1 = (UInt16)(value.register.uint16_1 * (UInt16)(object)factor);
- product.register.uint16_2 = (UInt16)(value.register.uint16_2 * (UInt16)(object)factor);
- product.register.uint16_3 = (UInt16)(value.register.uint16_3 * (UInt16)(object)factor);
- product.register.uint16_4 = (UInt16)(value.register.uint16_4 * (UInt16)(object)factor);
- product.register.uint16_5 = (UInt16)(value.register.uint16_5 * (UInt16)(object)factor);
- product.register.uint16_6 = (UInt16)(value.register.uint16_6 * (UInt16)(object)factor);
- product.register.uint16_7 = (UInt16)(value.register.uint16_7 * (UInt16)(object)factor);
- }
- else if (typeof(T) == typeof(Int16))
- {
- product.register.int16_0 = (Int16)(value.register.int16_0 * (Int16)(object)factor);
- product.register.int16_1 = (Int16)(value.register.int16_1 * (Int16)(object)factor);
- product.register.int16_2 = (Int16)(value.register.int16_2 * (Int16)(object)factor);
- product.register.int16_3 = (Int16)(value.register.int16_3 * (Int16)(object)factor);
- product.register.int16_4 = (Int16)(value.register.int16_4 * (Int16)(object)factor);
- product.register.int16_5 = (Int16)(value.register.int16_5 * (Int16)(object)factor);
- product.register.int16_6 = (Int16)(value.register.int16_6 * (Int16)(object)factor);
- product.register.int16_7 = (Int16)(value.register.int16_7 * (Int16)(object)factor);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- product.register.uint32_0 = (UInt32)(value.register.uint32_0 * (UInt32)(object)factor);
- product.register.uint32_1 = (UInt32)(value.register.uint32_1 * (UInt32)(object)factor);
- product.register.uint32_2 = (UInt32)(value.register.uint32_2 * (UInt32)(object)factor);
- product.register.uint32_3 = (UInt32)(value.register.uint32_3 * (UInt32)(object)factor);
- }
- else if (typeof(T) == typeof(Int32))
- {
- product.register.int32_0 = (Int32)(value.register.int32_0 * (Int32)(object)factor);
- product.register.int32_1 = (Int32)(value.register.int32_1 * (Int32)(object)factor);
- product.register.int32_2 = (Int32)(value.register.int32_2 * (Int32)(object)factor);
- product.register.int32_3 = (Int32)(value.register.int32_3 * (Int32)(object)factor);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- product.register.uint64_0 = (UInt64)(value.register.uint64_0 * (UInt64)(object)factor);
- product.register.uint64_1 = (UInt64)(value.register.uint64_1 * (UInt64)(object)factor);
- }
- else if (typeof(T) == typeof(Int64))
- {
- product.register.int64_0 = (Int64)(value.register.int64_0 * (Int64)(object)factor);
- product.register.int64_1 = (Int64)(value.register.int64_1 * (Int64)(object)factor);
- }
- else if (typeof(T) == typeof(Single))
- {
- product.register.single_0 = (Single)(value.register.single_0 * (Single)(object)factor);
- product.register.single_1 = (Single)(value.register.single_1 * (Single)(object)factor);
- product.register.single_2 = (Single)(value.register.single_2 * (Single)(object)factor);
- product.register.single_3 = (Single)(value.register.single_3 * (Single)(object)factor);
- }
- else if (typeof(T) == typeof(Double))
- {
- product.register.double_0 = (Double)(value.register.double_0 * (Double)(object)factor);
- product.register.double_1 = (Double)(value.register.double_1 * (Double)(object)factor);
+ if (typeof(T) == typeof(byte))
+ {
+ product.register.byte_0 = (byte)(value.register.byte_0 * (byte)(object)factor);
+ product.register.byte_1 = (byte)(value.register.byte_1 * (byte)(object)factor);
+ product.register.byte_2 = (byte)(value.register.byte_2 * (byte)(object)factor);
+ product.register.byte_3 = (byte)(value.register.byte_3 * (byte)(object)factor);
+ product.register.byte_4 = (byte)(value.register.byte_4 * (byte)(object)factor);
+ product.register.byte_5 = (byte)(value.register.byte_5 * (byte)(object)factor);
+ product.register.byte_6 = (byte)(value.register.byte_6 * (byte)(object)factor);
+ product.register.byte_7 = (byte)(value.register.byte_7 * (byte)(object)factor);
+ product.register.byte_8 = (byte)(value.register.byte_8 * (byte)(object)factor);
+ product.register.byte_9 = (byte)(value.register.byte_9 * (byte)(object)factor);
+ product.register.byte_10 = (byte)(value.register.byte_10 * (byte)(object)factor);
+ product.register.byte_11 = (byte)(value.register.byte_11 * (byte)(object)factor);
+ product.register.byte_12 = (byte)(value.register.byte_12 * (byte)(object)factor);
+ product.register.byte_13 = (byte)(value.register.byte_13 * (byte)(object)factor);
+ product.register.byte_14 = (byte)(value.register.byte_14 * (byte)(object)factor);
+ product.register.byte_15 = (byte)(value.register.byte_15 * (byte)(object)factor);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ product.register.sbyte_0 = (sbyte)(value.register.sbyte_0 * (sbyte)(object)factor);
+ product.register.sbyte_1 = (sbyte)(value.register.sbyte_1 * (sbyte)(object)factor);
+ product.register.sbyte_2 = (sbyte)(value.register.sbyte_2 * (sbyte)(object)factor);
+ product.register.sbyte_3 = (sbyte)(value.register.sbyte_3 * (sbyte)(object)factor);
+ product.register.sbyte_4 = (sbyte)(value.register.sbyte_4 * (sbyte)(object)factor);
+ product.register.sbyte_5 = (sbyte)(value.register.sbyte_5 * (sbyte)(object)factor);
+ product.register.sbyte_6 = (sbyte)(value.register.sbyte_6 * (sbyte)(object)factor);
+ product.register.sbyte_7 = (sbyte)(value.register.sbyte_7 * (sbyte)(object)factor);
+ product.register.sbyte_8 = (sbyte)(value.register.sbyte_8 * (sbyte)(object)factor);
+ product.register.sbyte_9 = (sbyte)(value.register.sbyte_9 * (sbyte)(object)factor);
+ product.register.sbyte_10 = (sbyte)(value.register.sbyte_10 * (sbyte)(object)factor);
+ product.register.sbyte_11 = (sbyte)(value.register.sbyte_11 * (sbyte)(object)factor);
+ product.register.sbyte_12 = (sbyte)(value.register.sbyte_12 * (sbyte)(object)factor);
+ product.register.sbyte_13 = (sbyte)(value.register.sbyte_13 * (sbyte)(object)factor);
+ product.register.sbyte_14 = (sbyte)(value.register.sbyte_14 * (sbyte)(object)factor);
+ product.register.sbyte_15 = (sbyte)(value.register.sbyte_15 * (sbyte)(object)factor);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ product.register.uint16_0 = (ushort)(value.register.uint16_0 * (ushort)(object)factor);
+ product.register.uint16_1 = (ushort)(value.register.uint16_1 * (ushort)(object)factor);
+ product.register.uint16_2 = (ushort)(value.register.uint16_2 * (ushort)(object)factor);
+ product.register.uint16_3 = (ushort)(value.register.uint16_3 * (ushort)(object)factor);
+ product.register.uint16_4 = (ushort)(value.register.uint16_4 * (ushort)(object)factor);
+ product.register.uint16_5 = (ushort)(value.register.uint16_5 * (ushort)(object)factor);
+ product.register.uint16_6 = (ushort)(value.register.uint16_6 * (ushort)(object)factor);
+ product.register.uint16_7 = (ushort)(value.register.uint16_7 * (ushort)(object)factor);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ product.register.int16_0 = (short)(value.register.int16_0 * (short)(object)factor);
+ product.register.int16_1 = (short)(value.register.int16_1 * (short)(object)factor);
+ product.register.int16_2 = (short)(value.register.int16_2 * (short)(object)factor);
+ product.register.int16_3 = (short)(value.register.int16_3 * (short)(object)factor);
+ product.register.int16_4 = (short)(value.register.int16_4 * (short)(object)factor);
+ product.register.int16_5 = (short)(value.register.int16_5 * (short)(object)factor);
+ product.register.int16_6 = (short)(value.register.int16_6 * (short)(object)factor);
+ product.register.int16_7 = (short)(value.register.int16_7 * (short)(object)factor);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ product.register.uint32_0 = (uint)(value.register.uint32_0 * (uint)(object)factor);
+ product.register.uint32_1 = (uint)(value.register.uint32_1 * (uint)(object)factor);
+ product.register.uint32_2 = (uint)(value.register.uint32_2 * (uint)(object)factor);
+ product.register.uint32_3 = (uint)(value.register.uint32_3 * (uint)(object)factor);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ product.register.int32_0 = (int)(value.register.int32_0 * (int)(object)factor);
+ product.register.int32_1 = (int)(value.register.int32_1 * (int)(object)factor);
+ product.register.int32_2 = (int)(value.register.int32_2 * (int)(object)factor);
+ product.register.int32_3 = (int)(value.register.int32_3 * (int)(object)factor);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ product.register.uint64_0 = (ulong)(value.register.uint64_0 * (ulong)(object)factor);
+ product.register.uint64_1 = (ulong)(value.register.uint64_1 * (ulong)(object)factor);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ product.register.int64_0 = (long)(value.register.int64_0 * (long)(object)factor);
+ product.register.int64_1 = (long)(value.register.int64_1 * (long)(object)factor);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ product.register.single_0 = (float)(value.register.single_0 * (float)(object)factor);
+ product.register.single_1 = (float)(value.register.single_1 * (float)(object)factor);
+ product.register.single_2 = (float)(value.register.single_2 * (float)(object)factor);
+ product.register.single_3 = (float)(value.register.single_3 * (float)(object)factor);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ product.register.double_0 = (double)(value.register.double_0 * (double)(object)factor);
+ product.register.double_1 = (double)(value.register.double_1 * (double)(object)factor);
}
return product;
}
@@ -2321,101 +2356,101 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- product.register.byte_0 = (Byte)(value.register.byte_0 * (Byte)(object)factor);
- product.register.byte_1 = (Byte)(value.register.byte_1 * (Byte)(object)factor);
- product.register.byte_2 = (Byte)(value.register.byte_2 * (Byte)(object)factor);
- product.register.byte_3 = (Byte)(value.register.byte_3 * (Byte)(object)factor);
- product.register.byte_4 = (Byte)(value.register.byte_4 * (Byte)(object)factor);
- product.register.byte_5 = (Byte)(value.register.byte_5 * (Byte)(object)factor);
- product.register.byte_6 = (Byte)(value.register.byte_6 * (Byte)(object)factor);
- product.register.byte_7 = (Byte)(value.register.byte_7 * (Byte)(object)factor);
- product.register.byte_8 = (Byte)(value.register.byte_8 * (Byte)(object)factor);
- product.register.byte_9 = (Byte)(value.register.byte_9 * (Byte)(object)factor);
- product.register.byte_10 = (Byte)(value.register.byte_10 * (Byte)(object)factor);
- product.register.byte_11 = (Byte)(value.register.byte_11 * (Byte)(object)factor);
- product.register.byte_12 = (Byte)(value.register.byte_12 * (Byte)(object)factor);
- product.register.byte_13 = (Byte)(value.register.byte_13 * (Byte)(object)factor);
- product.register.byte_14 = (Byte)(value.register.byte_14 * (Byte)(object)factor);
- product.register.byte_15 = (Byte)(value.register.byte_15 * (Byte)(object)factor);
- }
- else if (typeof(T) == typeof(SByte))
- {
- product.register.sbyte_0 = (SByte)(value.register.sbyte_0 * (SByte)(object)factor);
- product.register.sbyte_1 = (SByte)(value.register.sbyte_1 * (SByte)(object)factor);
- product.register.sbyte_2 = (SByte)(value.register.sbyte_2 * (SByte)(object)factor);
- product.register.sbyte_3 = (SByte)(value.register.sbyte_3 * (SByte)(object)factor);
- product.register.sbyte_4 = (SByte)(value.register.sbyte_4 * (SByte)(object)factor);
- product.register.sbyte_5 = (SByte)(value.register.sbyte_5 * (SByte)(object)factor);
- product.register.sbyte_6 = (SByte)(value.register.sbyte_6 * (SByte)(object)factor);
- product.register.sbyte_7 = (SByte)(value.register.sbyte_7 * (SByte)(object)factor);
- product.register.sbyte_8 = (SByte)(value.register.sbyte_8 * (SByte)(object)factor);
- product.register.sbyte_9 = (SByte)(value.register.sbyte_9 * (SByte)(object)factor);
- product.register.sbyte_10 = (SByte)(value.register.sbyte_10 * (SByte)(object)factor);
- product.register.sbyte_11 = (SByte)(value.register.sbyte_11 * (SByte)(object)factor);
- product.register.sbyte_12 = (SByte)(value.register.sbyte_12 * (SByte)(object)factor);
- product.register.sbyte_13 = (SByte)(value.register.sbyte_13 * (SByte)(object)factor);
- product.register.sbyte_14 = (SByte)(value.register.sbyte_14 * (SByte)(object)factor);
- product.register.sbyte_15 = (SByte)(value.register.sbyte_15 * (SByte)(object)factor);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- product.register.uint16_0 = (UInt16)(value.register.uint16_0 * (UInt16)(object)factor);
- product.register.uint16_1 = (UInt16)(value.register.uint16_1 * (UInt16)(object)factor);
- product.register.uint16_2 = (UInt16)(value.register.uint16_2 * (UInt16)(object)factor);
- product.register.uint16_3 = (UInt16)(value.register.uint16_3 * (UInt16)(object)factor);
- product.register.uint16_4 = (UInt16)(value.register.uint16_4 * (UInt16)(object)factor);
- product.register.uint16_5 = (UInt16)(value.register.uint16_5 * (UInt16)(object)factor);
- product.register.uint16_6 = (UInt16)(value.register.uint16_6 * (UInt16)(object)factor);
- product.register.uint16_7 = (UInt16)(value.register.uint16_7 * (UInt16)(object)factor);
- }
- else if (typeof(T) == typeof(Int16))
- {
- product.register.int16_0 = (Int16)(value.register.int16_0 * (Int16)(object)factor);
- product.register.int16_1 = (Int16)(value.register.int16_1 * (Int16)(object)factor);
- product.register.int16_2 = (Int16)(value.register.int16_2 * (Int16)(object)factor);
- product.register.int16_3 = (Int16)(value.register.int16_3 * (Int16)(object)factor);
- product.register.int16_4 = (Int16)(value.register.int16_4 * (Int16)(object)factor);
- product.register.int16_5 = (Int16)(value.register.int16_5 * (Int16)(object)factor);
- product.register.int16_6 = (Int16)(value.register.int16_6 * (Int16)(object)factor);
- product.register.int16_7 = (Int16)(value.register.int16_7 * (Int16)(object)factor);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- product.register.uint32_0 = (UInt32)(value.register.uint32_0 * (UInt32)(object)factor);
- product.register.uint32_1 = (UInt32)(value.register.uint32_1 * (UInt32)(object)factor);
- product.register.uint32_2 = (UInt32)(value.register.uint32_2 * (UInt32)(object)factor);
- product.register.uint32_3 = (UInt32)(value.register.uint32_3 * (UInt32)(object)factor);
- }
- else if (typeof(T) == typeof(Int32))
- {
- product.register.int32_0 = (Int32)(value.register.int32_0 * (Int32)(object)factor);
- product.register.int32_1 = (Int32)(value.register.int32_1 * (Int32)(object)factor);
- product.register.int32_2 = (Int32)(value.register.int32_2 * (Int32)(object)factor);
- product.register.int32_3 = (Int32)(value.register.int32_3 * (Int32)(object)factor);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- product.register.uint64_0 = (UInt64)(value.register.uint64_0 * (UInt64)(object)factor);
- product.register.uint64_1 = (UInt64)(value.register.uint64_1 * (UInt64)(object)factor);
- }
- else if (typeof(T) == typeof(Int64))
- {
- product.register.int64_0 = (Int64)(value.register.int64_0 * (Int64)(object)factor);
- product.register.int64_1 = (Int64)(value.register.int64_1 * (Int64)(object)factor);
- }
- else if (typeof(T) == typeof(Single))
- {
- product.register.single_0 = (Single)(value.register.single_0 * (Single)(object)factor);
- product.register.single_1 = (Single)(value.register.single_1 * (Single)(object)factor);
- product.register.single_2 = (Single)(value.register.single_2 * (Single)(object)factor);
- product.register.single_3 = (Single)(value.register.single_3 * (Single)(object)factor);
- }
- else if (typeof(T) == typeof(Double))
- {
- product.register.double_0 = (Double)(value.register.double_0 * (Double)(object)factor);
- product.register.double_1 = (Double)(value.register.double_1 * (Double)(object)factor);
+ if (typeof(T) == typeof(byte))
+ {
+ product.register.byte_0 = (byte)(value.register.byte_0 * (byte)(object)factor);
+ product.register.byte_1 = (byte)(value.register.byte_1 * (byte)(object)factor);
+ product.register.byte_2 = (byte)(value.register.byte_2 * (byte)(object)factor);
+ product.register.byte_3 = (byte)(value.register.byte_3 * (byte)(object)factor);
+ product.register.byte_4 = (byte)(value.register.byte_4 * (byte)(object)factor);
+ product.register.byte_5 = (byte)(value.register.byte_5 * (byte)(object)factor);
+ product.register.byte_6 = (byte)(value.register.byte_6 * (byte)(object)factor);
+ product.register.byte_7 = (byte)(value.register.byte_7 * (byte)(object)factor);
+ product.register.byte_8 = (byte)(value.register.byte_8 * (byte)(object)factor);
+ product.register.byte_9 = (byte)(value.register.byte_9 * (byte)(object)factor);
+ product.register.byte_10 = (byte)(value.register.byte_10 * (byte)(object)factor);
+ product.register.byte_11 = (byte)(value.register.byte_11 * (byte)(object)factor);
+ product.register.byte_12 = (byte)(value.register.byte_12 * (byte)(object)factor);
+ product.register.byte_13 = (byte)(value.register.byte_13 * (byte)(object)factor);
+ product.register.byte_14 = (byte)(value.register.byte_14 * (byte)(object)factor);
+ product.register.byte_15 = (byte)(value.register.byte_15 * (byte)(object)factor);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ product.register.sbyte_0 = (sbyte)(value.register.sbyte_0 * (sbyte)(object)factor);
+ product.register.sbyte_1 = (sbyte)(value.register.sbyte_1 * (sbyte)(object)factor);
+ product.register.sbyte_2 = (sbyte)(value.register.sbyte_2 * (sbyte)(object)factor);
+ product.register.sbyte_3 = (sbyte)(value.register.sbyte_3 * (sbyte)(object)factor);
+ product.register.sbyte_4 = (sbyte)(value.register.sbyte_4 * (sbyte)(object)factor);
+ product.register.sbyte_5 = (sbyte)(value.register.sbyte_5 * (sbyte)(object)factor);
+ product.register.sbyte_6 = (sbyte)(value.register.sbyte_6 * (sbyte)(object)factor);
+ product.register.sbyte_7 = (sbyte)(value.register.sbyte_7 * (sbyte)(object)factor);
+ product.register.sbyte_8 = (sbyte)(value.register.sbyte_8 * (sbyte)(object)factor);
+ product.register.sbyte_9 = (sbyte)(value.register.sbyte_9 * (sbyte)(object)factor);
+ product.register.sbyte_10 = (sbyte)(value.register.sbyte_10 * (sbyte)(object)factor);
+ product.register.sbyte_11 = (sbyte)(value.register.sbyte_11 * (sbyte)(object)factor);
+ product.register.sbyte_12 = (sbyte)(value.register.sbyte_12 * (sbyte)(object)factor);
+ product.register.sbyte_13 = (sbyte)(value.register.sbyte_13 * (sbyte)(object)factor);
+ product.register.sbyte_14 = (sbyte)(value.register.sbyte_14 * (sbyte)(object)factor);
+ product.register.sbyte_15 = (sbyte)(value.register.sbyte_15 * (sbyte)(object)factor);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ product.register.uint16_0 = (ushort)(value.register.uint16_0 * (ushort)(object)factor);
+ product.register.uint16_1 = (ushort)(value.register.uint16_1 * (ushort)(object)factor);
+ product.register.uint16_2 = (ushort)(value.register.uint16_2 * (ushort)(object)factor);
+ product.register.uint16_3 = (ushort)(value.register.uint16_3 * (ushort)(object)factor);
+ product.register.uint16_4 = (ushort)(value.register.uint16_4 * (ushort)(object)factor);
+ product.register.uint16_5 = (ushort)(value.register.uint16_5 * (ushort)(object)factor);
+ product.register.uint16_6 = (ushort)(value.register.uint16_6 * (ushort)(object)factor);
+ product.register.uint16_7 = (ushort)(value.register.uint16_7 * (ushort)(object)factor);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ product.register.int16_0 = (short)(value.register.int16_0 * (short)(object)factor);
+ product.register.int16_1 = (short)(value.register.int16_1 * (short)(object)factor);
+ product.register.int16_2 = (short)(value.register.int16_2 * (short)(object)factor);
+ product.register.int16_3 = (short)(value.register.int16_3 * (short)(object)factor);
+ product.register.int16_4 = (short)(value.register.int16_4 * (short)(object)factor);
+ product.register.int16_5 = (short)(value.register.int16_5 * (short)(object)factor);
+ product.register.int16_6 = (short)(value.register.int16_6 * (short)(object)factor);
+ product.register.int16_7 = (short)(value.register.int16_7 * (short)(object)factor);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ product.register.uint32_0 = (uint)(value.register.uint32_0 * (uint)(object)factor);
+ product.register.uint32_1 = (uint)(value.register.uint32_1 * (uint)(object)factor);
+ product.register.uint32_2 = (uint)(value.register.uint32_2 * (uint)(object)factor);
+ product.register.uint32_3 = (uint)(value.register.uint32_3 * (uint)(object)factor);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ product.register.int32_0 = (int)(value.register.int32_0 * (int)(object)factor);
+ product.register.int32_1 = (int)(value.register.int32_1 * (int)(object)factor);
+ product.register.int32_2 = (int)(value.register.int32_2 * (int)(object)factor);
+ product.register.int32_3 = (int)(value.register.int32_3 * (int)(object)factor);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ product.register.uint64_0 = (ulong)(value.register.uint64_0 * (ulong)(object)factor);
+ product.register.uint64_1 = (ulong)(value.register.uint64_1 * (ulong)(object)factor);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ product.register.int64_0 = (long)(value.register.int64_0 * (long)(object)factor);
+ product.register.int64_1 = (long)(value.register.int64_1 * (long)(object)factor);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ product.register.single_0 = (float)(value.register.single_0 * (float)(object)factor);
+ product.register.single_1 = (float)(value.register.single_1 * (float)(object)factor);
+ product.register.single_2 = (float)(value.register.single_2 * (float)(object)factor);
+ product.register.single_3 = (float)(value.register.single_3 * (float)(object)factor);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ product.register.double_0 = (double)(value.register.double_0 * (double)(object)factor);
+ product.register.double_1 = (double)(value.register.double_1 * (double)(object)factor);
}
return product;
}
@@ -2435,93 +2470,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -2533,101 +2568,101 @@ namespace System.Numerics
else
{
Vector<T> quotient = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- quotient.register.byte_0 = (Byte)(left.register.byte_0 / right.register.byte_0);
- quotient.register.byte_1 = (Byte)(left.register.byte_1 / right.register.byte_1);
- quotient.register.byte_2 = (Byte)(left.register.byte_2 / right.register.byte_2);
- quotient.register.byte_3 = (Byte)(left.register.byte_3 / right.register.byte_3);
- quotient.register.byte_4 = (Byte)(left.register.byte_4 / right.register.byte_4);
- quotient.register.byte_5 = (Byte)(left.register.byte_5 / right.register.byte_5);
- quotient.register.byte_6 = (Byte)(left.register.byte_6 / right.register.byte_6);
- quotient.register.byte_7 = (Byte)(left.register.byte_7 / right.register.byte_7);
- quotient.register.byte_8 = (Byte)(left.register.byte_8 / right.register.byte_8);
- quotient.register.byte_9 = (Byte)(left.register.byte_9 / right.register.byte_9);
- quotient.register.byte_10 = (Byte)(left.register.byte_10 / right.register.byte_10);
- quotient.register.byte_11 = (Byte)(left.register.byte_11 / right.register.byte_11);
- quotient.register.byte_12 = (Byte)(left.register.byte_12 / right.register.byte_12);
- quotient.register.byte_13 = (Byte)(left.register.byte_13 / right.register.byte_13);
- quotient.register.byte_14 = (Byte)(left.register.byte_14 / right.register.byte_14);
- quotient.register.byte_15 = (Byte)(left.register.byte_15 / right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- quotient.register.sbyte_0 = (SByte)(left.register.sbyte_0 / right.register.sbyte_0);
- quotient.register.sbyte_1 = (SByte)(left.register.sbyte_1 / right.register.sbyte_1);
- quotient.register.sbyte_2 = (SByte)(left.register.sbyte_2 / right.register.sbyte_2);
- quotient.register.sbyte_3 = (SByte)(left.register.sbyte_3 / right.register.sbyte_3);
- quotient.register.sbyte_4 = (SByte)(left.register.sbyte_4 / right.register.sbyte_4);
- quotient.register.sbyte_5 = (SByte)(left.register.sbyte_5 / right.register.sbyte_5);
- quotient.register.sbyte_6 = (SByte)(left.register.sbyte_6 / right.register.sbyte_6);
- quotient.register.sbyte_7 = (SByte)(left.register.sbyte_7 / right.register.sbyte_7);
- quotient.register.sbyte_8 = (SByte)(left.register.sbyte_8 / right.register.sbyte_8);
- quotient.register.sbyte_9 = (SByte)(left.register.sbyte_9 / right.register.sbyte_9);
- quotient.register.sbyte_10 = (SByte)(left.register.sbyte_10 / right.register.sbyte_10);
- quotient.register.sbyte_11 = (SByte)(left.register.sbyte_11 / right.register.sbyte_11);
- quotient.register.sbyte_12 = (SByte)(left.register.sbyte_12 / right.register.sbyte_12);
- quotient.register.sbyte_13 = (SByte)(left.register.sbyte_13 / right.register.sbyte_13);
- quotient.register.sbyte_14 = (SByte)(left.register.sbyte_14 / right.register.sbyte_14);
- quotient.register.sbyte_15 = (SByte)(left.register.sbyte_15 / right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- quotient.register.uint16_0 = (UInt16)(left.register.uint16_0 / right.register.uint16_0);
- quotient.register.uint16_1 = (UInt16)(left.register.uint16_1 / right.register.uint16_1);
- quotient.register.uint16_2 = (UInt16)(left.register.uint16_2 / right.register.uint16_2);
- quotient.register.uint16_3 = (UInt16)(left.register.uint16_3 / right.register.uint16_3);
- quotient.register.uint16_4 = (UInt16)(left.register.uint16_4 / right.register.uint16_4);
- quotient.register.uint16_5 = (UInt16)(left.register.uint16_5 / right.register.uint16_5);
- quotient.register.uint16_6 = (UInt16)(left.register.uint16_6 / right.register.uint16_6);
- quotient.register.uint16_7 = (UInt16)(left.register.uint16_7 / right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- quotient.register.int16_0 = (Int16)(left.register.int16_0 / right.register.int16_0);
- quotient.register.int16_1 = (Int16)(left.register.int16_1 / right.register.int16_1);
- quotient.register.int16_2 = (Int16)(left.register.int16_2 / right.register.int16_2);
- quotient.register.int16_3 = (Int16)(left.register.int16_3 / right.register.int16_3);
- quotient.register.int16_4 = (Int16)(left.register.int16_4 / right.register.int16_4);
- quotient.register.int16_5 = (Int16)(left.register.int16_5 / right.register.int16_5);
- quotient.register.int16_6 = (Int16)(left.register.int16_6 / right.register.int16_6);
- quotient.register.int16_7 = (Int16)(left.register.int16_7 / right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- quotient.register.uint32_0 = (UInt32)(left.register.uint32_0 / right.register.uint32_0);
- quotient.register.uint32_1 = (UInt32)(left.register.uint32_1 / right.register.uint32_1);
- quotient.register.uint32_2 = (UInt32)(left.register.uint32_2 / right.register.uint32_2);
- quotient.register.uint32_3 = (UInt32)(left.register.uint32_3 / right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- quotient.register.int32_0 = (Int32)(left.register.int32_0 / right.register.int32_0);
- quotient.register.int32_1 = (Int32)(left.register.int32_1 / right.register.int32_1);
- quotient.register.int32_2 = (Int32)(left.register.int32_2 / right.register.int32_2);
- quotient.register.int32_3 = (Int32)(left.register.int32_3 / right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- quotient.register.uint64_0 = (UInt64)(left.register.uint64_0 / right.register.uint64_0);
- quotient.register.uint64_1 = (UInt64)(left.register.uint64_1 / right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- quotient.register.int64_0 = (Int64)(left.register.int64_0 / right.register.int64_0);
- quotient.register.int64_1 = (Int64)(left.register.int64_1 / right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- quotient.register.single_0 = (Single)(left.register.single_0 / right.register.single_0);
- quotient.register.single_1 = (Single)(left.register.single_1 / right.register.single_1);
- quotient.register.single_2 = (Single)(left.register.single_2 / right.register.single_2);
- quotient.register.single_3 = (Single)(left.register.single_3 / right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- quotient.register.double_0 = (Double)(left.register.double_0 / right.register.double_0);
- quotient.register.double_1 = (Double)(left.register.double_1 / right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ quotient.register.byte_0 = (byte)(left.register.byte_0 / right.register.byte_0);
+ quotient.register.byte_1 = (byte)(left.register.byte_1 / right.register.byte_1);
+ quotient.register.byte_2 = (byte)(left.register.byte_2 / right.register.byte_2);
+ quotient.register.byte_3 = (byte)(left.register.byte_3 / right.register.byte_3);
+ quotient.register.byte_4 = (byte)(left.register.byte_4 / right.register.byte_4);
+ quotient.register.byte_5 = (byte)(left.register.byte_5 / right.register.byte_5);
+ quotient.register.byte_6 = (byte)(left.register.byte_6 / right.register.byte_6);
+ quotient.register.byte_7 = (byte)(left.register.byte_7 / right.register.byte_7);
+ quotient.register.byte_8 = (byte)(left.register.byte_8 / right.register.byte_8);
+ quotient.register.byte_9 = (byte)(left.register.byte_9 / right.register.byte_9);
+ quotient.register.byte_10 = (byte)(left.register.byte_10 / right.register.byte_10);
+ quotient.register.byte_11 = (byte)(left.register.byte_11 / right.register.byte_11);
+ quotient.register.byte_12 = (byte)(left.register.byte_12 / right.register.byte_12);
+ quotient.register.byte_13 = (byte)(left.register.byte_13 / right.register.byte_13);
+ quotient.register.byte_14 = (byte)(left.register.byte_14 / right.register.byte_14);
+ quotient.register.byte_15 = (byte)(left.register.byte_15 / right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ quotient.register.sbyte_0 = (sbyte)(left.register.sbyte_0 / right.register.sbyte_0);
+ quotient.register.sbyte_1 = (sbyte)(left.register.sbyte_1 / right.register.sbyte_1);
+ quotient.register.sbyte_2 = (sbyte)(left.register.sbyte_2 / right.register.sbyte_2);
+ quotient.register.sbyte_3 = (sbyte)(left.register.sbyte_3 / right.register.sbyte_3);
+ quotient.register.sbyte_4 = (sbyte)(left.register.sbyte_4 / right.register.sbyte_4);
+ quotient.register.sbyte_5 = (sbyte)(left.register.sbyte_5 / right.register.sbyte_5);
+ quotient.register.sbyte_6 = (sbyte)(left.register.sbyte_6 / right.register.sbyte_6);
+ quotient.register.sbyte_7 = (sbyte)(left.register.sbyte_7 / right.register.sbyte_7);
+ quotient.register.sbyte_8 = (sbyte)(left.register.sbyte_8 / right.register.sbyte_8);
+ quotient.register.sbyte_9 = (sbyte)(left.register.sbyte_9 / right.register.sbyte_9);
+ quotient.register.sbyte_10 = (sbyte)(left.register.sbyte_10 / right.register.sbyte_10);
+ quotient.register.sbyte_11 = (sbyte)(left.register.sbyte_11 / right.register.sbyte_11);
+ quotient.register.sbyte_12 = (sbyte)(left.register.sbyte_12 / right.register.sbyte_12);
+ quotient.register.sbyte_13 = (sbyte)(left.register.sbyte_13 / right.register.sbyte_13);
+ quotient.register.sbyte_14 = (sbyte)(left.register.sbyte_14 / right.register.sbyte_14);
+ quotient.register.sbyte_15 = (sbyte)(left.register.sbyte_15 / right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ quotient.register.uint16_0 = (ushort)(left.register.uint16_0 / right.register.uint16_0);
+ quotient.register.uint16_1 = (ushort)(left.register.uint16_1 / right.register.uint16_1);
+ quotient.register.uint16_2 = (ushort)(left.register.uint16_2 / right.register.uint16_2);
+ quotient.register.uint16_3 = (ushort)(left.register.uint16_3 / right.register.uint16_3);
+ quotient.register.uint16_4 = (ushort)(left.register.uint16_4 / right.register.uint16_4);
+ quotient.register.uint16_5 = (ushort)(left.register.uint16_5 / right.register.uint16_5);
+ quotient.register.uint16_6 = (ushort)(left.register.uint16_6 / right.register.uint16_6);
+ quotient.register.uint16_7 = (ushort)(left.register.uint16_7 / right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ quotient.register.int16_0 = (short)(left.register.int16_0 / right.register.int16_0);
+ quotient.register.int16_1 = (short)(left.register.int16_1 / right.register.int16_1);
+ quotient.register.int16_2 = (short)(left.register.int16_2 / right.register.int16_2);
+ quotient.register.int16_3 = (short)(left.register.int16_3 / right.register.int16_3);
+ quotient.register.int16_4 = (short)(left.register.int16_4 / right.register.int16_4);
+ quotient.register.int16_5 = (short)(left.register.int16_5 / right.register.int16_5);
+ quotient.register.int16_6 = (short)(left.register.int16_6 / right.register.int16_6);
+ quotient.register.int16_7 = (short)(left.register.int16_7 / right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ quotient.register.uint32_0 = (uint)(left.register.uint32_0 / right.register.uint32_0);
+ quotient.register.uint32_1 = (uint)(left.register.uint32_1 / right.register.uint32_1);
+ quotient.register.uint32_2 = (uint)(left.register.uint32_2 / right.register.uint32_2);
+ quotient.register.uint32_3 = (uint)(left.register.uint32_3 / right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ quotient.register.int32_0 = (int)(left.register.int32_0 / right.register.int32_0);
+ quotient.register.int32_1 = (int)(left.register.int32_1 / right.register.int32_1);
+ quotient.register.int32_2 = (int)(left.register.int32_2 / right.register.int32_2);
+ quotient.register.int32_3 = (int)(left.register.int32_3 / right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ quotient.register.uint64_0 = (ulong)(left.register.uint64_0 / right.register.uint64_0);
+ quotient.register.uint64_1 = (ulong)(left.register.uint64_1 / right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ quotient.register.int64_0 = (long)(left.register.int64_0 / right.register.int64_0);
+ quotient.register.int64_1 = (long)(left.register.int64_1 / right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ quotient.register.single_0 = (float)(left.register.single_0 / right.register.single_0);
+ quotient.register.single_1 = (float)(left.register.single_1 / right.register.single_1);
+ quotient.register.single_2 = (float)(left.register.single_2 / right.register.single_2);
+ quotient.register.single_3 = (float)(left.register.single_3 / right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ quotient.register.double_0 = (double)(left.register.double_0 / right.register.double_0);
+ quotient.register.double_1 = (double)(left.register.double_1 / right.register.double_1);
}
return quotient;
}
@@ -2660,10 +2695,10 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] & rightBase[g];
}
@@ -2691,10 +2726,10 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] | rightBase[g];
}
@@ -2722,10 +2757,10 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] ^ rightBase[g];
}
@@ -2784,9 +2819,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Byte>(Vector<T> value)
+ public static explicit operator Vector<byte>(Vector<T> value)
{
- return new Vector<Byte>(ref value.register);
+ return new Vector<byte>(ref value.register);
}
/// <summary>
@@ -2796,9 +2831,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<SByte>(Vector<T> value)
+ public static explicit operator Vector<sbyte>(Vector<T> value)
{
- return new Vector<SByte>(ref value.register);
+ return new Vector<sbyte>(ref value.register);
}
/// <summary>
@@ -2808,9 +2843,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<UInt16>(Vector<T> value)
+ public static explicit operator Vector<ushort>(Vector<T> value)
{
- return new Vector<UInt16>(ref value.register);
+ return new Vector<ushort>(ref value.register);
}
/// <summary>
@@ -2819,9 +2854,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Int16>(Vector<T> value)
+ public static explicit operator Vector<short>(Vector<T> value)
{
- return new Vector<Int16>(ref value.register);
+ return new Vector<short>(ref value.register);
}
/// <summary>
@@ -2831,9 +2866,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<UInt32>(Vector<T> value)
+ public static explicit operator Vector<uint>(Vector<T> value)
{
- return new Vector<UInt32>(ref value.register);
+ return new Vector<uint>(ref value.register);
}
/// <summary>
@@ -2842,9 +2877,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Int32>(Vector<T> value)
+ public static explicit operator Vector<int>(Vector<T> value)
{
- return new Vector<Int32>(ref value.register);
+ return new Vector<int>(ref value.register);
}
/// <summary>
@@ -2854,9 +2889,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<UInt64>(Vector<T> value)
+ public static explicit operator Vector<ulong>(Vector<T> value)
{
- return new Vector<UInt64>(ref value.register);
+ return new Vector<ulong>(ref value.register);
}
/// <summary>
@@ -2865,9 +2900,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Int64>(Vector<T> value)
+ public static explicit operator Vector<long>(Vector<T> value)
{
- return new Vector<Int64>(ref value.register);
+ return new Vector<long>(ref value.register);
}
/// <summary>
@@ -2876,9 +2911,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Single>(Vector<T> value)
+ public static explicit operator Vector<float>(Vector<T> value)
{
- return new Vector<Single>(ref value.register);
+ return new Vector<float>(ref value.register);
}
/// <summary>
@@ -2887,9 +2922,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Double>(Vector<T> value)
+ public static explicit operator Vector<double>(Vector<T> value)
{
- return new Vector<Double>(ref value.register);
+ return new Vector<double>(ref value.register);
}
#endregion Conversions
@@ -2901,93 +2936,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
}
return new Vector<T>(dataPtr);
}
@@ -2999,110 +3034,110 @@ namespace System.Numerics
else
{
Register register = new Register();
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = left.register.byte_0 == right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_1 = left.register.byte_1 == right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_2 = left.register.byte_2 == right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_3 = left.register.byte_3 == right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_4 = left.register.byte_4 == right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_5 = left.register.byte_5 == right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_6 = left.register.byte_6 == right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_7 = left.register.byte_7 == right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_8 = left.register.byte_8 == right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_9 = left.register.byte_9 == right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_10 = left.register.byte_10 == right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_11 = left.register.byte_11 == right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_12 = left.register.byte_12 == right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_13 = left.register.byte_13 == right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_14 = left.register.byte_14 == right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_15 = left.register.byte_15 == right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = left.register.byte_0 == right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_1 = left.register.byte_1 == right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_2 = left.register.byte_2 == right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_3 = left.register.byte_3 == right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_4 = left.register.byte_4 == right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_5 = left.register.byte_5 == right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_6 = left.register.byte_6 == right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_7 = left.register.byte_7 == right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_8 = left.register.byte_8 == right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_9 = left.register.byte_9 == right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_10 = left.register.byte_10 == right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_11 = left.register.byte_11 == right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_12 = left.register.byte_12 == right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_13 = left.register.byte_13 == right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_14 = left.register.byte_14 == right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_15 = left.register.byte_15 == right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = left.register.sbyte_0 == right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_1 = left.register.sbyte_1 == right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_2 = left.register.sbyte_2 == right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_3 = left.register.sbyte_3 == right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_4 = left.register.sbyte_4 == right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_5 = left.register.sbyte_5 == right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_6 = left.register.sbyte_6 == right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_7 = left.register.sbyte_7 == right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_8 = left.register.sbyte_8 == right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_9 = left.register.sbyte_9 == right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_10 = left.register.sbyte_10 == right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_11 = left.register.sbyte_11 == right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_12 = left.register.sbyte_12 == right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_13 = left.register.sbyte_13 == right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_14 = left.register.sbyte_14 == right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_15 = left.register.sbyte_15 == right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = left.register.sbyte_0 == right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_1 = left.register.sbyte_1 == right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_2 = left.register.sbyte_2 == right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_3 = left.register.sbyte_3 == right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_4 = left.register.sbyte_4 == right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_5 = left.register.sbyte_5 == right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_6 = left.register.sbyte_6 == right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_7 = left.register.sbyte_7 == right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_8 = left.register.sbyte_8 == right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_9 = left.register.sbyte_9 == right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_10 = left.register.sbyte_10 == right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_11 = left.register.sbyte_11 == right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_12 = left.register.sbyte_12 == right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_13 = left.register.sbyte_13 == right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_14 = left.register.sbyte_14 == right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_15 = left.register.sbyte_15 == right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- register.uint16_0 = left.register.uint16_0 == right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_1 = left.register.uint16_1 == right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_2 = left.register.uint16_2 == right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_3 = left.register.uint16_3 == right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_4 = left.register.uint16_4 == right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_5 = left.register.uint16_5 == right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_6 = left.register.uint16_6 == right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_7 = left.register.uint16_7 == right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ register.uint16_0 = left.register.uint16_0 == right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_1 = left.register.uint16_1 == right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_2 = left.register.uint16_2 == right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_3 = left.register.uint16_3 == right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_4 = left.register.uint16_4 == right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_5 = left.register.uint16_5 == right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_6 = left.register.uint16_6 == right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_7 = left.register.uint16_7 == right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- register.int16_0 = left.register.int16_0 == right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_1 = left.register.int16_1 == right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_2 = left.register.int16_2 == right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_3 = left.register.int16_3 == right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_4 = left.register.int16_4 == right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_5 = left.register.int16_5 == right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_6 = left.register.int16_6 == right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_7 = left.register.int16_7 == right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ register.int16_0 = left.register.int16_0 == right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_1 = left.register.int16_1 == right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_2 = left.register.int16_2 == right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_3 = left.register.int16_3 == right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_4 = left.register.int16_4 == right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_5 = left.register.int16_5 == right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_6 = left.register.int16_6 == right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_7 = left.register.int16_7 == right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- register.uint32_0 = left.register.uint32_0 == right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_1 = left.register.uint32_1 == right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_2 = left.register.uint32_2 == right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_3 = left.register.uint32_3 == right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ register.uint32_0 = left.register.uint32_0 == right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_1 = left.register.uint32_1 == right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_2 = left.register.uint32_2 == right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_3 = left.register.uint32_3 == right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- register.int32_0 = left.register.int32_0 == right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_1 = left.register.int32_1 == right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_2 = left.register.int32_2 == right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_3 = left.register.int32_3 == right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ register.int32_0 = left.register.int32_0 == right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_1 = left.register.int32_1 == right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_2 = left.register.int32_2 == right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_3 = left.register.int32_3 == right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- register.uint64_0 = left.register.uint64_0 == right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
- register.uint64_1 = left.register.uint64_1 == right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ register.uint64_0 = left.register.uint64_0 == right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
+ register.uint64_1 = left.register.uint64_1 == right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- register.int64_0 = left.register.int64_0 == right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
- register.int64_1 = left.register.int64_1 == right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ register.int64_0 = left.register.int64_0 == right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
+ register.int64_1 = left.register.int64_1 == right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- register.single_0 = left.register.single_0 == right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_1 = left.register.single_1 == right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_2 = left.register.single_2 == right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_3 = left.register.single_3 == right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ register.single_0 = left.register.single_0 == right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_1 = left.register.single_1 == right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_2 = left.register.single_2 == right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_3 = left.register.single_3 == right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- register.double_0 = left.register.double_0 == right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
- register.double_1 = left.register.double_1 == right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ register.double_0 = left.register.double_0 == right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
+ register.double_1 = left.register.double_1 == right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
return new Vector<T>(ref register);
}
else
@@ -3118,93 +3153,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
}
return new Vector<T>(dataPtr);
}
@@ -3216,110 +3251,110 @@ namespace System.Numerics
else
{
Register register = new Register();
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = left.register.byte_0 < right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_1 = left.register.byte_1 < right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_2 = left.register.byte_2 < right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_3 = left.register.byte_3 < right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_4 = left.register.byte_4 < right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_5 = left.register.byte_5 < right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_6 = left.register.byte_6 < right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_7 = left.register.byte_7 < right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_8 = left.register.byte_8 < right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_9 = left.register.byte_9 < right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_10 = left.register.byte_10 < right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_11 = left.register.byte_11 < right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_12 = left.register.byte_12 < right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_13 = left.register.byte_13 < right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_14 = left.register.byte_14 < right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_15 = left.register.byte_15 < right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = left.register.byte_0 < right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_1 = left.register.byte_1 < right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_2 = left.register.byte_2 < right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_3 = left.register.byte_3 < right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_4 = left.register.byte_4 < right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_5 = left.register.byte_5 < right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_6 = left.register.byte_6 < right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_7 = left.register.byte_7 < right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_8 = left.register.byte_8 < right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_9 = left.register.byte_9 < right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_10 = left.register.byte_10 < right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_11 = left.register.byte_11 < right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_12 = left.register.byte_12 < right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_13 = left.register.byte_13 < right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_14 = left.register.byte_14 < right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_15 = left.register.byte_15 < right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = left.register.sbyte_0 < right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_1 = left.register.sbyte_1 < right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_2 = left.register.sbyte_2 < right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_3 = left.register.sbyte_3 < right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_4 = left.register.sbyte_4 < right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_5 = left.register.sbyte_5 < right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_6 = left.register.sbyte_6 < right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_7 = left.register.sbyte_7 < right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_8 = left.register.sbyte_8 < right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_9 = left.register.sbyte_9 < right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_10 = left.register.sbyte_10 < right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_11 = left.register.sbyte_11 < right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_12 = left.register.sbyte_12 < right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_13 = left.register.sbyte_13 < right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_14 = left.register.sbyte_14 < right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_15 = left.register.sbyte_15 < right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = left.register.sbyte_0 < right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_1 = left.register.sbyte_1 < right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_2 = left.register.sbyte_2 < right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_3 = left.register.sbyte_3 < right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_4 = left.register.sbyte_4 < right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_5 = left.register.sbyte_5 < right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_6 = left.register.sbyte_6 < right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_7 = left.register.sbyte_7 < right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_8 = left.register.sbyte_8 < right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_9 = left.register.sbyte_9 < right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_10 = left.register.sbyte_10 < right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_11 = left.register.sbyte_11 < right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_12 = left.register.sbyte_12 < right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_13 = left.register.sbyte_13 < right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_14 = left.register.sbyte_14 < right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_15 = left.register.sbyte_15 < right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- register.uint16_0 = left.register.uint16_0 < right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_1 = left.register.uint16_1 < right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_2 = left.register.uint16_2 < right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_3 = left.register.uint16_3 < right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_4 = left.register.uint16_4 < right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_5 = left.register.uint16_5 < right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_6 = left.register.uint16_6 < right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_7 = left.register.uint16_7 < right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ register.uint16_0 = left.register.uint16_0 < right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_1 = left.register.uint16_1 < right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_2 = left.register.uint16_2 < right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_3 = left.register.uint16_3 < right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_4 = left.register.uint16_4 < right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_5 = left.register.uint16_5 < right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_6 = left.register.uint16_6 < right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_7 = left.register.uint16_7 < right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- register.int16_0 = left.register.int16_0 < right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_1 = left.register.int16_1 < right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_2 = left.register.int16_2 < right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_3 = left.register.int16_3 < right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_4 = left.register.int16_4 < right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_5 = left.register.int16_5 < right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_6 = left.register.int16_6 < right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_7 = left.register.int16_7 < right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ register.int16_0 = left.register.int16_0 < right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_1 = left.register.int16_1 < right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_2 = left.register.int16_2 < right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_3 = left.register.int16_3 < right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_4 = left.register.int16_4 < right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_5 = left.register.int16_5 < right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_6 = left.register.int16_6 < right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_7 = left.register.int16_7 < right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- register.uint32_0 = left.register.uint32_0 < right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_1 = left.register.uint32_1 < right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_2 = left.register.uint32_2 < right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_3 = left.register.uint32_3 < right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ register.uint32_0 = left.register.uint32_0 < right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_1 = left.register.uint32_1 < right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_2 = left.register.uint32_2 < right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_3 = left.register.uint32_3 < right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- register.int32_0 = left.register.int32_0 < right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_1 = left.register.int32_1 < right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_2 = left.register.int32_2 < right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_3 = left.register.int32_3 < right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ register.int32_0 = left.register.int32_0 < right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_1 = left.register.int32_1 < right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_2 = left.register.int32_2 < right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_3 = left.register.int32_3 < right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- register.uint64_0 = left.register.uint64_0 < right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
- register.uint64_1 = left.register.uint64_1 < right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ register.uint64_0 = left.register.uint64_0 < right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
+ register.uint64_1 = left.register.uint64_1 < right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- register.int64_0 = left.register.int64_0 < right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
- register.int64_1 = left.register.int64_1 < right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ register.int64_0 = left.register.int64_0 < right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
+ register.int64_1 = left.register.int64_1 < right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- register.single_0 = left.register.single_0 < right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_1 = left.register.single_1 < right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_2 = left.register.single_2 < right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_3 = left.register.single_3 < right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ register.single_0 = left.register.single_0 < right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_1 = left.register.single_1 < right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_2 = left.register.single_2 < right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_3 = left.register.single_3 < right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- register.double_0 = left.register.double_0 < right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
- register.double_1 = left.register.double_1 < right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ register.double_0 = left.register.double_0 < right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
+ register.double_1 = left.register.double_1 < right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
return new Vector<T>(ref register);
}
else
@@ -3335,93 +3370,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
}
return new Vector<T>(dataPtr);
}
@@ -3433,110 +3468,110 @@ namespace System.Numerics
else
{
Register register = new Register();
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = left.register.byte_0 > right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_1 = left.register.byte_1 > right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_2 = left.register.byte_2 > right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_3 = left.register.byte_3 > right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_4 = left.register.byte_4 > right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_5 = left.register.byte_5 > right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_6 = left.register.byte_6 > right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_7 = left.register.byte_7 > right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_8 = left.register.byte_8 > right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_9 = left.register.byte_9 > right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_10 = left.register.byte_10 > right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_11 = left.register.byte_11 > right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_12 = left.register.byte_12 > right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_13 = left.register.byte_13 > right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_14 = left.register.byte_14 > right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_15 = left.register.byte_15 > right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = left.register.byte_0 > right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_1 = left.register.byte_1 > right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_2 = left.register.byte_2 > right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_3 = left.register.byte_3 > right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_4 = left.register.byte_4 > right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_5 = left.register.byte_5 > right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_6 = left.register.byte_6 > right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_7 = left.register.byte_7 > right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_8 = left.register.byte_8 > right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_9 = left.register.byte_9 > right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_10 = left.register.byte_10 > right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_11 = left.register.byte_11 > right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_12 = left.register.byte_12 > right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_13 = left.register.byte_13 > right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_14 = left.register.byte_14 > right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_15 = left.register.byte_15 > right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = left.register.sbyte_0 > right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_1 = left.register.sbyte_1 > right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_2 = left.register.sbyte_2 > right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_3 = left.register.sbyte_3 > right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_4 = left.register.sbyte_4 > right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_5 = left.register.sbyte_5 > right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_6 = left.register.sbyte_6 > right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_7 = left.register.sbyte_7 > right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_8 = left.register.sbyte_8 > right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_9 = left.register.sbyte_9 > right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_10 = left.register.sbyte_10 > right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_11 = left.register.sbyte_11 > right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_12 = left.register.sbyte_12 > right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_13 = left.register.sbyte_13 > right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_14 = left.register.sbyte_14 > right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_15 = left.register.sbyte_15 > right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = left.register.sbyte_0 > right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_1 = left.register.sbyte_1 > right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_2 = left.register.sbyte_2 > right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_3 = left.register.sbyte_3 > right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_4 = left.register.sbyte_4 > right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_5 = left.register.sbyte_5 > right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_6 = left.register.sbyte_6 > right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_7 = left.register.sbyte_7 > right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_8 = left.register.sbyte_8 > right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_9 = left.register.sbyte_9 > right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_10 = left.register.sbyte_10 > right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_11 = left.register.sbyte_11 > right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_12 = left.register.sbyte_12 > right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_13 = left.register.sbyte_13 > right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_14 = left.register.sbyte_14 > right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_15 = left.register.sbyte_15 > right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- register.uint16_0 = left.register.uint16_0 > right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_1 = left.register.uint16_1 > right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_2 = left.register.uint16_2 > right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_3 = left.register.uint16_3 > right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_4 = left.register.uint16_4 > right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_5 = left.register.uint16_5 > right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_6 = left.register.uint16_6 > right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_7 = left.register.uint16_7 > right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ register.uint16_0 = left.register.uint16_0 > right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_1 = left.register.uint16_1 > right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_2 = left.register.uint16_2 > right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_3 = left.register.uint16_3 > right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_4 = left.register.uint16_4 > right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_5 = left.register.uint16_5 > right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_6 = left.register.uint16_6 > right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_7 = left.register.uint16_7 > right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- register.int16_0 = left.register.int16_0 > right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_1 = left.register.int16_1 > right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_2 = left.register.int16_2 > right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_3 = left.register.int16_3 > right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_4 = left.register.int16_4 > right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_5 = left.register.int16_5 > right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_6 = left.register.int16_6 > right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_7 = left.register.int16_7 > right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ register.int16_0 = left.register.int16_0 > right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_1 = left.register.int16_1 > right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_2 = left.register.int16_2 > right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_3 = left.register.int16_3 > right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_4 = left.register.int16_4 > right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_5 = left.register.int16_5 > right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_6 = left.register.int16_6 > right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_7 = left.register.int16_7 > right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- register.uint32_0 = left.register.uint32_0 > right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_1 = left.register.uint32_1 > right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_2 = left.register.uint32_2 > right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_3 = left.register.uint32_3 > right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ register.uint32_0 = left.register.uint32_0 > right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_1 = left.register.uint32_1 > right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_2 = left.register.uint32_2 > right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_3 = left.register.uint32_3 > right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- register.int32_0 = left.register.int32_0 > right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_1 = left.register.int32_1 > right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_2 = left.register.int32_2 > right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_3 = left.register.int32_3 > right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ register.int32_0 = left.register.int32_0 > right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_1 = left.register.int32_1 > right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_2 = left.register.int32_2 > right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_3 = left.register.int32_3 > right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- register.uint64_0 = left.register.uint64_0 > right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
- register.uint64_1 = left.register.uint64_1 > right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ register.uint64_0 = left.register.uint64_0 > right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
+ register.uint64_1 = left.register.uint64_1 > right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- register.int64_0 = left.register.int64_0 > right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
- register.int64_1 = left.register.int64_1 > right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ register.int64_0 = left.register.int64_0 > right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
+ register.int64_1 = left.register.int64_1 > right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- register.single_0 = left.register.single_0 > right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_1 = left.register.single_1 > right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_2 = left.register.single_2 > right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_3 = left.register.single_3 > right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ register.single_0 = left.register.single_0 > right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_1 = left.register.single_1 > right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_2 = left.register.single_2 > right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_3 = left.register.single_3 > right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- register.double_0 = left.register.double_0 > right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
- register.double_1 = left.register.double_1 > right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ register.double_0 = left.register.double_0 > right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
+ register.double_1 = left.register.double_1 > right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
return new Vector<T>(ref register);
}
else
@@ -3569,75 +3604,75 @@ namespace System.Numerics
[Intrinsic]
internal static unsafe Vector<T> Abs(Vector<T> value)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
return value;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
return value;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
return value;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
return value;
}
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(SByte))
+ if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)(Math.Abs((SByte)(object)value[g]));
+ dataPtr[g] = (sbyte)(object)(Math.Abs((sbyte)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)(Math.Abs((Int16)(object)value[g]));
+ dataPtr[g] = (short)(object)(Math.Abs((short)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)(Math.Abs((Int32)(object)value[g]));
+ dataPtr[g] = (int)(object)(Math.Abs((int)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)(Math.Abs((Int64)(object)value[g]));
+ dataPtr[g] = (long)(object)(Math.Abs((long)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)(Math.Abs((Single)(object)value[g]));
+ dataPtr[g] = (float)(object)(Math.Abs((float)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)(Math.Abs((Double)(object)value[g]));
+ dataPtr[g] = (double)(object)(Math.Abs((double)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
@@ -3648,64 +3683,64 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(SByte))
- {
- value.register.sbyte_0 = (SByte)(Math.Abs(value.register.sbyte_0));
- value.register.sbyte_1 = (SByte)(Math.Abs(value.register.sbyte_1));
- value.register.sbyte_2 = (SByte)(Math.Abs(value.register.sbyte_2));
- value.register.sbyte_3 = (SByte)(Math.Abs(value.register.sbyte_3));
- value.register.sbyte_4 = (SByte)(Math.Abs(value.register.sbyte_4));
- value.register.sbyte_5 = (SByte)(Math.Abs(value.register.sbyte_5));
- value.register.sbyte_6 = (SByte)(Math.Abs(value.register.sbyte_6));
- value.register.sbyte_7 = (SByte)(Math.Abs(value.register.sbyte_7));
- value.register.sbyte_8 = (SByte)(Math.Abs(value.register.sbyte_8));
- value.register.sbyte_9 = (SByte)(Math.Abs(value.register.sbyte_9));
- value.register.sbyte_10 = (SByte)(Math.Abs(value.register.sbyte_10));
- value.register.sbyte_11 = (SByte)(Math.Abs(value.register.sbyte_11));
- value.register.sbyte_12 = (SByte)(Math.Abs(value.register.sbyte_12));
- value.register.sbyte_13 = (SByte)(Math.Abs(value.register.sbyte_13));
- value.register.sbyte_14 = (SByte)(Math.Abs(value.register.sbyte_14));
- value.register.sbyte_15 = (SByte)(Math.Abs(value.register.sbyte_15));
+ if (typeof(T) == typeof(sbyte))
+ {
+ value.register.sbyte_0 = (sbyte)(Math.Abs(value.register.sbyte_0));
+ value.register.sbyte_1 = (sbyte)(Math.Abs(value.register.sbyte_1));
+ value.register.sbyte_2 = (sbyte)(Math.Abs(value.register.sbyte_2));
+ value.register.sbyte_3 = (sbyte)(Math.Abs(value.register.sbyte_3));
+ value.register.sbyte_4 = (sbyte)(Math.Abs(value.register.sbyte_4));
+ value.register.sbyte_5 = (sbyte)(Math.Abs(value.register.sbyte_5));
+ value.register.sbyte_6 = (sbyte)(Math.Abs(value.register.sbyte_6));
+ value.register.sbyte_7 = (sbyte)(Math.Abs(value.register.sbyte_7));
+ value.register.sbyte_8 = (sbyte)(Math.Abs(value.register.sbyte_8));
+ value.register.sbyte_9 = (sbyte)(Math.Abs(value.register.sbyte_9));
+ value.register.sbyte_10 = (sbyte)(Math.Abs(value.register.sbyte_10));
+ value.register.sbyte_11 = (sbyte)(Math.Abs(value.register.sbyte_11));
+ value.register.sbyte_12 = (sbyte)(Math.Abs(value.register.sbyte_12));
+ value.register.sbyte_13 = (sbyte)(Math.Abs(value.register.sbyte_13));
+ value.register.sbyte_14 = (sbyte)(Math.Abs(value.register.sbyte_14));
+ value.register.sbyte_15 = (sbyte)(Math.Abs(value.register.sbyte_15));
return value;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- value.register.int16_0 = (Int16)(Math.Abs(value.register.int16_0));
- value.register.int16_1 = (Int16)(Math.Abs(value.register.int16_1));
- value.register.int16_2 = (Int16)(Math.Abs(value.register.int16_2));
- value.register.int16_3 = (Int16)(Math.Abs(value.register.int16_3));
- value.register.int16_4 = (Int16)(Math.Abs(value.register.int16_4));
- value.register.int16_5 = (Int16)(Math.Abs(value.register.int16_5));
- value.register.int16_6 = (Int16)(Math.Abs(value.register.int16_6));
- value.register.int16_7 = (Int16)(Math.Abs(value.register.int16_7));
+ value.register.int16_0 = (short)(Math.Abs(value.register.int16_0));
+ value.register.int16_1 = (short)(Math.Abs(value.register.int16_1));
+ value.register.int16_2 = (short)(Math.Abs(value.register.int16_2));
+ value.register.int16_3 = (short)(Math.Abs(value.register.int16_3));
+ value.register.int16_4 = (short)(Math.Abs(value.register.int16_4));
+ value.register.int16_5 = (short)(Math.Abs(value.register.int16_5));
+ value.register.int16_6 = (short)(Math.Abs(value.register.int16_6));
+ value.register.int16_7 = (short)(Math.Abs(value.register.int16_7));
return value;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- value.register.int32_0 = (Int32)(Math.Abs(value.register.int32_0));
- value.register.int32_1 = (Int32)(Math.Abs(value.register.int32_1));
- value.register.int32_2 = (Int32)(Math.Abs(value.register.int32_2));
- value.register.int32_3 = (Int32)(Math.Abs(value.register.int32_3));
+ value.register.int32_0 = (int)(Math.Abs(value.register.int32_0));
+ value.register.int32_1 = (int)(Math.Abs(value.register.int32_1));
+ value.register.int32_2 = (int)(Math.Abs(value.register.int32_2));
+ value.register.int32_3 = (int)(Math.Abs(value.register.int32_3));
return value;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- value.register.int64_0 = (Int64)(Math.Abs(value.register.int64_0));
- value.register.int64_1 = (Int64)(Math.Abs(value.register.int64_1));
+ value.register.int64_0 = (long)(Math.Abs(value.register.int64_0));
+ value.register.int64_1 = (long)(Math.Abs(value.register.int64_1));
return value;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- value.register.single_0 = (Single)(Math.Abs(value.register.single_0));
- value.register.single_1 = (Single)(Math.Abs(value.register.single_1));
- value.register.single_2 = (Single)(Math.Abs(value.register.single_2));
- value.register.single_3 = (Single)(Math.Abs(value.register.single_3));
+ value.register.single_0 = (float)(Math.Abs(value.register.single_0));
+ value.register.single_1 = (float)(Math.Abs(value.register.single_1));
+ value.register.single_2 = (float)(Math.Abs(value.register.single_2));
+ value.register.single_3 = (float)(Math.Abs(value.register.single_3));
return value;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- value.register.double_0 = (Double)(Math.Abs(value.register.double_0));
- value.register.double_1 = (Double)(Math.Abs(value.register.double_1));
+ value.register.double_0 = (double)(Math.Abs(value.register.double_0));
+ value.register.double_1 = (double)(Math.Abs(value.register.double_1));
return value;
}
else
@@ -3720,93 +3755,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Byte)(object)left[g] : (Byte)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (byte)(object)left[g] : (byte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (SByte)(object)left[g] : (SByte)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (sbyte)(object)left[g] : (sbyte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (UInt16)(object)left[g] : (UInt16)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (ushort)(object)left[g] : (ushort)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Int16)(object)left[g] : (Int16)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (short)(object)left[g] : (short)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (UInt32)(object)left[g] : (UInt32)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (uint)(object)left[g] : (uint)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Int32)(object)left[g] : (Int32)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (int)(object)left[g] : (int)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (UInt64)(object)left[g] : (UInt64)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (ulong)(object)left[g] : (ulong)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Int64)(object)left[g] : (Int64)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (long)(object)left[g] : (long)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Single)(object)left[g] : (Single)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (float)(object)left[g] : (float)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Double)(object)left[g] : (Double)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (double)(object)left[g] : (double)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -3818,7 +3853,7 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
vec.register.byte_0 = left.register.byte_0 < right.register.byte_0 ? left.register.byte_0 : right.register.byte_0;
vec.register.byte_1 = left.register.byte_1 < right.register.byte_1 ? left.register.byte_1 : right.register.byte_1;
@@ -3838,7 +3873,7 @@ namespace System.Numerics
vec.register.byte_15 = left.register.byte_15 < right.register.byte_15 ? left.register.byte_15 : right.register.byte_15;
return vec;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
vec.register.sbyte_0 = left.register.sbyte_0 < right.register.sbyte_0 ? left.register.sbyte_0 : right.register.sbyte_0;
vec.register.sbyte_1 = left.register.sbyte_1 < right.register.sbyte_1 ? left.register.sbyte_1 : right.register.sbyte_1;
@@ -3858,7 +3893,7 @@ namespace System.Numerics
vec.register.sbyte_15 = left.register.sbyte_15 < right.register.sbyte_15 ? left.register.sbyte_15 : right.register.sbyte_15;
return vec;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
vec.register.uint16_0 = left.register.uint16_0 < right.register.uint16_0 ? left.register.uint16_0 : right.register.uint16_0;
vec.register.uint16_1 = left.register.uint16_1 < right.register.uint16_1 ? left.register.uint16_1 : right.register.uint16_1;
@@ -3870,7 +3905,7 @@ namespace System.Numerics
vec.register.uint16_7 = left.register.uint16_7 < right.register.uint16_7 ? left.register.uint16_7 : right.register.uint16_7;
return vec;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
vec.register.int16_0 = left.register.int16_0 < right.register.int16_0 ? left.register.int16_0 : right.register.int16_0;
vec.register.int16_1 = left.register.int16_1 < right.register.int16_1 ? left.register.int16_1 : right.register.int16_1;
@@ -3882,7 +3917,7 @@ namespace System.Numerics
vec.register.int16_7 = left.register.int16_7 < right.register.int16_7 ? left.register.int16_7 : right.register.int16_7;
return vec;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
vec.register.uint32_0 = left.register.uint32_0 < right.register.uint32_0 ? left.register.uint32_0 : right.register.uint32_0;
vec.register.uint32_1 = left.register.uint32_1 < right.register.uint32_1 ? left.register.uint32_1 : right.register.uint32_1;
@@ -3890,7 +3925,7 @@ namespace System.Numerics
vec.register.uint32_3 = left.register.uint32_3 < right.register.uint32_3 ? left.register.uint32_3 : right.register.uint32_3;
return vec;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
vec.register.int32_0 = left.register.int32_0 < right.register.int32_0 ? left.register.int32_0 : right.register.int32_0;
vec.register.int32_1 = left.register.int32_1 < right.register.int32_1 ? left.register.int32_1 : right.register.int32_1;
@@ -3898,19 +3933,19 @@ namespace System.Numerics
vec.register.int32_3 = left.register.int32_3 < right.register.int32_3 ? left.register.int32_3 : right.register.int32_3;
return vec;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
vec.register.uint64_0 = left.register.uint64_0 < right.register.uint64_0 ? left.register.uint64_0 : right.register.uint64_0;
vec.register.uint64_1 = left.register.uint64_1 < right.register.uint64_1 ? left.register.uint64_1 : right.register.uint64_1;
return vec;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
vec.register.int64_0 = left.register.int64_0 < right.register.int64_0 ? left.register.int64_0 : right.register.int64_0;
vec.register.int64_1 = left.register.int64_1 < right.register.int64_1 ? left.register.int64_1 : right.register.int64_1;
return vec;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
vec.register.single_0 = left.register.single_0 < right.register.single_0 ? left.register.single_0 : right.register.single_0;
vec.register.single_1 = left.register.single_1 < right.register.single_1 ? left.register.single_1 : right.register.single_1;
@@ -3918,7 +3953,7 @@ namespace System.Numerics
vec.register.single_3 = left.register.single_3 < right.register.single_3 ? left.register.single_3 : right.register.single_3;
return vec;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
vec.register.double_0 = left.register.double_0 < right.register.double_0 ? left.register.double_0 : right.register.double_0;
vec.register.double_1 = left.register.double_1 < right.register.double_1 ? left.register.double_1 : right.register.double_1;
@@ -3936,93 +3971,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Byte)(object)left[g] : (Byte)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (byte)(object)left[g] : (byte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (SByte)(object)left[g] : (SByte)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (sbyte)(object)left[g] : (sbyte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (UInt16)(object)left[g] : (UInt16)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (ushort)(object)left[g] : (ushort)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Int16)(object)left[g] : (Int16)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (short)(object)left[g] : (short)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (UInt32)(object)left[g] : (UInt32)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (uint)(object)left[g] : (uint)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Int32)(object)left[g] : (Int32)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (int)(object)left[g] : (int)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (UInt64)(object)left[g] : (UInt64)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (ulong)(object)left[g] : (ulong)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Int64)(object)left[g] : (Int64)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (long)(object)left[g] : (long)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Single)(object)left[g] : (Single)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (float)(object)left[g] : (float)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Double)(object)left[g] : (Double)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (double)(object)left[g] : (double)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -4034,7 +4069,7 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
vec.register.byte_0 = left.register.byte_0 > right.register.byte_0 ? left.register.byte_0 : right.register.byte_0;
vec.register.byte_1 = left.register.byte_1 > right.register.byte_1 ? left.register.byte_1 : right.register.byte_1;
@@ -4054,7 +4089,7 @@ namespace System.Numerics
vec.register.byte_15 = left.register.byte_15 > right.register.byte_15 ? left.register.byte_15 : right.register.byte_15;
return vec;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
vec.register.sbyte_0 = left.register.sbyte_0 > right.register.sbyte_0 ? left.register.sbyte_0 : right.register.sbyte_0;
vec.register.sbyte_1 = left.register.sbyte_1 > right.register.sbyte_1 ? left.register.sbyte_1 : right.register.sbyte_1;
@@ -4074,7 +4109,7 @@ namespace System.Numerics
vec.register.sbyte_15 = left.register.sbyte_15 > right.register.sbyte_15 ? left.register.sbyte_15 : right.register.sbyte_15;
return vec;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
vec.register.uint16_0 = left.register.uint16_0 > right.register.uint16_0 ? left.register.uint16_0 : right.register.uint16_0;
vec.register.uint16_1 = left.register.uint16_1 > right.register.uint16_1 ? left.register.uint16_1 : right.register.uint16_1;
@@ -4086,7 +4121,7 @@ namespace System.Numerics
vec.register.uint16_7 = left.register.uint16_7 > right.register.uint16_7 ? left.register.uint16_7 : right.register.uint16_7;
return vec;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
vec.register.int16_0 = left.register.int16_0 > right.register.int16_0 ? left.register.int16_0 : right.register.int16_0;
vec.register.int16_1 = left.register.int16_1 > right.register.int16_1 ? left.register.int16_1 : right.register.int16_1;
@@ -4098,7 +4133,7 @@ namespace System.Numerics
vec.register.int16_7 = left.register.int16_7 > right.register.int16_7 ? left.register.int16_7 : right.register.int16_7;
return vec;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
vec.register.uint32_0 = left.register.uint32_0 > right.register.uint32_0 ? left.register.uint32_0 : right.register.uint32_0;
vec.register.uint32_1 = left.register.uint32_1 > right.register.uint32_1 ? left.register.uint32_1 : right.register.uint32_1;
@@ -4106,7 +4141,7 @@ namespace System.Numerics
vec.register.uint32_3 = left.register.uint32_3 > right.register.uint32_3 ? left.register.uint32_3 : right.register.uint32_3;
return vec;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
vec.register.int32_0 = left.register.int32_0 > right.register.int32_0 ? left.register.int32_0 : right.register.int32_0;
vec.register.int32_1 = left.register.int32_1 > right.register.int32_1 ? left.register.int32_1 : right.register.int32_1;
@@ -4114,19 +4149,19 @@ namespace System.Numerics
vec.register.int32_3 = left.register.int32_3 > right.register.int32_3 ? left.register.int32_3 : right.register.int32_3;
return vec;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
vec.register.uint64_0 = left.register.uint64_0 > right.register.uint64_0 ? left.register.uint64_0 : right.register.uint64_0;
vec.register.uint64_1 = left.register.uint64_1 > right.register.uint64_1 ? left.register.uint64_1 : right.register.uint64_1;
return vec;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
vec.register.int64_0 = left.register.int64_0 > right.register.int64_0 ? left.register.int64_0 : right.register.int64_0;
vec.register.int64_1 = left.register.int64_1 > right.register.int64_1 ? left.register.int64_1 : right.register.int64_1;
return vec;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
vec.register.single_0 = left.register.single_0 > right.register.single_0 ? left.register.single_0 : right.register.single_0;
vec.register.single_1 = left.register.single_1 > right.register.single_1 ? left.register.single_1 : right.register.single_1;
@@ -4134,7 +4169,7 @@ namespace System.Numerics
vec.register.single_3 = left.register.single_3 > right.register.single_3 ? left.register.single_3 : right.register.single_3;
return vec;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
vec.register.double_0 = left.register.double_0 > right.register.double_0 ? left.register.double_0 : right.register.double_0;
vec.register.double_1 = left.register.double_1 > right.register.double_1 ? left.register.double_1 : right.register.double_1;
@@ -4161,120 +4196,120 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
- {
- Byte product = 0;
- product += (Byte)(left.register.byte_0 * right.register.byte_0);
- product += (Byte)(left.register.byte_1 * right.register.byte_1);
- product += (Byte)(left.register.byte_2 * right.register.byte_2);
- product += (Byte)(left.register.byte_3 * right.register.byte_3);
- product += (Byte)(left.register.byte_4 * right.register.byte_4);
- product += (Byte)(left.register.byte_5 * right.register.byte_5);
- product += (Byte)(left.register.byte_6 * right.register.byte_6);
- product += (Byte)(left.register.byte_7 * right.register.byte_7);
- product += (Byte)(left.register.byte_8 * right.register.byte_8);
- product += (Byte)(left.register.byte_9 * right.register.byte_9);
- product += (Byte)(left.register.byte_10 * right.register.byte_10);
- product += (Byte)(left.register.byte_11 * right.register.byte_11);
- product += (Byte)(left.register.byte_12 * right.register.byte_12);
- product += (Byte)(left.register.byte_13 * right.register.byte_13);
- product += (Byte)(left.register.byte_14 * right.register.byte_14);
- product += (Byte)(left.register.byte_15 * right.register.byte_15);
+ if (typeof(T) == typeof(byte))
+ {
+ byte product = 0;
+ product += (byte)(left.register.byte_0 * right.register.byte_0);
+ product += (byte)(left.register.byte_1 * right.register.byte_1);
+ product += (byte)(left.register.byte_2 * right.register.byte_2);
+ product += (byte)(left.register.byte_3 * right.register.byte_3);
+ product += (byte)(left.register.byte_4 * right.register.byte_4);
+ product += (byte)(left.register.byte_5 * right.register.byte_5);
+ product += (byte)(left.register.byte_6 * right.register.byte_6);
+ product += (byte)(left.register.byte_7 * right.register.byte_7);
+ product += (byte)(left.register.byte_8 * right.register.byte_8);
+ product += (byte)(left.register.byte_9 * right.register.byte_9);
+ product += (byte)(left.register.byte_10 * right.register.byte_10);
+ product += (byte)(left.register.byte_11 * right.register.byte_11);
+ product += (byte)(left.register.byte_12 * right.register.byte_12);
+ product += (byte)(left.register.byte_13 * right.register.byte_13);
+ product += (byte)(left.register.byte_14 * right.register.byte_14);
+ product += (byte)(left.register.byte_15 * right.register.byte_15);
return (T)(object)product;
}
- else if (typeof(T) == typeof(SByte))
- {
- SByte product = 0;
- product += (SByte)(left.register.sbyte_0 * right.register.sbyte_0);
- product += (SByte)(left.register.sbyte_1 * right.register.sbyte_1);
- product += (SByte)(left.register.sbyte_2 * right.register.sbyte_2);
- product += (SByte)(left.register.sbyte_3 * right.register.sbyte_3);
- product += (SByte)(left.register.sbyte_4 * right.register.sbyte_4);
- product += (SByte)(left.register.sbyte_5 * right.register.sbyte_5);
- product += (SByte)(left.register.sbyte_6 * right.register.sbyte_6);
- product += (SByte)(left.register.sbyte_7 * right.register.sbyte_7);
- product += (SByte)(left.register.sbyte_8 * right.register.sbyte_8);
- product += (SByte)(left.register.sbyte_9 * right.register.sbyte_9);
- product += (SByte)(left.register.sbyte_10 * right.register.sbyte_10);
- product += (SByte)(left.register.sbyte_11 * right.register.sbyte_11);
- product += (SByte)(left.register.sbyte_12 * right.register.sbyte_12);
- product += (SByte)(left.register.sbyte_13 * right.register.sbyte_13);
- product += (SByte)(left.register.sbyte_14 * right.register.sbyte_14);
- product += (SByte)(left.register.sbyte_15 * right.register.sbyte_15);
+ else if (typeof(T) == typeof(sbyte))
+ {
+ sbyte product = 0;
+ product += (sbyte)(left.register.sbyte_0 * right.register.sbyte_0);
+ product += (sbyte)(left.register.sbyte_1 * right.register.sbyte_1);
+ product += (sbyte)(left.register.sbyte_2 * right.register.sbyte_2);
+ product += (sbyte)(left.register.sbyte_3 * right.register.sbyte_3);
+ product += (sbyte)(left.register.sbyte_4 * right.register.sbyte_4);
+ product += (sbyte)(left.register.sbyte_5 * right.register.sbyte_5);
+ product += (sbyte)(left.register.sbyte_6 * right.register.sbyte_6);
+ product += (sbyte)(left.register.sbyte_7 * right.register.sbyte_7);
+ product += (sbyte)(left.register.sbyte_8 * right.register.sbyte_8);
+ product += (sbyte)(left.register.sbyte_9 * right.register.sbyte_9);
+ product += (sbyte)(left.register.sbyte_10 * right.register.sbyte_10);
+ product += (sbyte)(left.register.sbyte_11 * right.register.sbyte_11);
+ product += (sbyte)(left.register.sbyte_12 * right.register.sbyte_12);
+ product += (sbyte)(left.register.sbyte_13 * right.register.sbyte_13);
+ product += (sbyte)(left.register.sbyte_14 * right.register.sbyte_14);
+ product += (sbyte)(left.register.sbyte_15 * right.register.sbyte_15);
return (T)(object)product;
}
- else if (typeof(T) == typeof(UInt16))
- {
- UInt16 product = 0;
- product += (UInt16)(left.register.uint16_0 * right.register.uint16_0);
- product += (UInt16)(left.register.uint16_1 * right.register.uint16_1);
- product += (UInt16)(left.register.uint16_2 * right.register.uint16_2);
- product += (UInt16)(left.register.uint16_3 * right.register.uint16_3);
- product += (UInt16)(left.register.uint16_4 * right.register.uint16_4);
- product += (UInt16)(left.register.uint16_5 * right.register.uint16_5);
- product += (UInt16)(left.register.uint16_6 * right.register.uint16_6);
- product += (UInt16)(left.register.uint16_7 * right.register.uint16_7);
+ else if (typeof(T) == typeof(ushort))
+ {
+ ushort product = 0;
+ product += (ushort)(left.register.uint16_0 * right.register.uint16_0);
+ product += (ushort)(left.register.uint16_1 * right.register.uint16_1);
+ product += (ushort)(left.register.uint16_2 * right.register.uint16_2);
+ product += (ushort)(left.register.uint16_3 * right.register.uint16_3);
+ product += (ushort)(left.register.uint16_4 * right.register.uint16_4);
+ product += (ushort)(left.register.uint16_5 * right.register.uint16_5);
+ product += (ushort)(left.register.uint16_6 * right.register.uint16_6);
+ product += (ushort)(left.register.uint16_7 * right.register.uint16_7);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Int16))
- {
- Int16 product = 0;
- product += (Int16)(left.register.int16_0 * right.register.int16_0);
- product += (Int16)(left.register.int16_1 * right.register.int16_1);
- product += (Int16)(left.register.int16_2 * right.register.int16_2);
- product += (Int16)(left.register.int16_3 * right.register.int16_3);
- product += (Int16)(left.register.int16_4 * right.register.int16_4);
- product += (Int16)(left.register.int16_5 * right.register.int16_5);
- product += (Int16)(left.register.int16_6 * right.register.int16_6);
- product += (Int16)(left.register.int16_7 * right.register.int16_7);
+ else if (typeof(T) == typeof(short))
+ {
+ short product = 0;
+ product += (short)(left.register.int16_0 * right.register.int16_0);
+ product += (short)(left.register.int16_1 * right.register.int16_1);
+ product += (short)(left.register.int16_2 * right.register.int16_2);
+ product += (short)(left.register.int16_3 * right.register.int16_3);
+ product += (short)(left.register.int16_4 * right.register.int16_4);
+ product += (short)(left.register.int16_5 * right.register.int16_5);
+ product += (short)(left.register.int16_6 * right.register.int16_6);
+ product += (short)(left.register.int16_7 * right.register.int16_7);
return (T)(object)product;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32 product = 0;
- product += (UInt32)(left.register.uint32_0 * right.register.uint32_0);
- product += (UInt32)(left.register.uint32_1 * right.register.uint32_1);
- product += (UInt32)(left.register.uint32_2 * right.register.uint32_2);
- product += (UInt32)(left.register.uint32_3 * right.register.uint32_3);
+ uint product = 0;
+ product += (uint)(left.register.uint32_0 * right.register.uint32_0);
+ product += (uint)(left.register.uint32_1 * right.register.uint32_1);
+ product += (uint)(left.register.uint32_2 * right.register.uint32_2);
+ product += (uint)(left.register.uint32_3 * right.register.uint32_3);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32 product = 0;
- product += (Int32)(left.register.int32_0 * right.register.int32_0);
- product += (Int32)(left.register.int32_1 * right.register.int32_1);
- product += (Int32)(left.register.int32_2 * right.register.int32_2);
- product += (Int32)(left.register.int32_3 * right.register.int32_3);
+ int product = 0;
+ product += (int)(left.register.int32_0 * right.register.int32_0);
+ product += (int)(left.register.int32_1 * right.register.int32_1);
+ product += (int)(left.register.int32_2 * right.register.int32_2);
+ product += (int)(left.register.int32_3 * right.register.int32_3);
return (T)(object)product;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64 product = 0;
- product += (UInt64)(left.register.uint64_0 * right.register.uint64_0);
- product += (UInt64)(left.register.uint64_1 * right.register.uint64_1);
+ ulong product = 0;
+ product += (ulong)(left.register.uint64_0 * right.register.uint64_0);
+ product += (ulong)(left.register.uint64_1 * right.register.uint64_1);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64 product = 0;
- product += (Int64)(left.register.int64_0 * right.register.int64_0);
- product += (Int64)(left.register.int64_1 * right.register.int64_1);
+ long product = 0;
+ product += (long)(left.register.int64_0 * right.register.int64_0);
+ product += (long)(left.register.int64_1 * right.register.int64_1);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single product = 0;
- product += (Single)(left.register.single_0 * right.register.single_0);
- product += (Single)(left.register.single_1 * right.register.single_1);
- product += (Single)(left.register.single_2 * right.register.single_2);
- product += (Single)(left.register.single_3 * right.register.single_3);
+ float product = 0;
+ product += (float)(left.register.single_0 * right.register.single_0);
+ product += (float)(left.register.single_1 * right.register.single_1);
+ product += (float)(left.register.single_2 * right.register.single_2);
+ product += (float)(left.register.single_3 * right.register.single_3);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double product = 0;
- product += (Double)(left.register.double_0 * right.register.double_0);
- product += (Double)(left.register.double_1 * right.register.double_1);
+ double product = 0;
+ product += (double)(left.register.double_0 * right.register.double_0);
+ product += (double)(left.register.double_1 * right.register.double_1);
return (T)(object)product;
}
else
@@ -4289,93 +4324,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Byte)Math.Sqrt((Byte)(object)value[g]));
+ dataPtr[g] = unchecked((byte)Math.Sqrt((byte)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((SByte)Math.Sqrt((SByte)(object)value[g]));
+ dataPtr[g] = unchecked((sbyte)Math.Sqrt((sbyte)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((UInt16)Math.Sqrt((UInt16)(object)value[g]));
+ dataPtr[g] = unchecked((ushort)Math.Sqrt((ushort)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Int16)Math.Sqrt((Int16)(object)value[g]));
+ dataPtr[g] = unchecked((short)Math.Sqrt((short)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((UInt32)Math.Sqrt((UInt32)(object)value[g]));
+ dataPtr[g] = unchecked((uint)Math.Sqrt((uint)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Int32)Math.Sqrt((Int32)(object)value[g]));
+ dataPtr[g] = unchecked((int)Math.Sqrt((int)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((UInt64)Math.Sqrt((UInt64)(object)value[g]));
+ dataPtr[g] = unchecked((ulong)Math.Sqrt((ulong)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Int64)Math.Sqrt((Int64)(object)value[g]));
+ dataPtr[g] = unchecked((long)Math.Sqrt((long)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Single)Math.Sqrt((Single)(object)value[g]));
+ dataPtr[g] = unchecked((float)Math.Sqrt((float)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Double)Math.Sqrt((Double)(object)value[g]));
+ dataPtr[g] = unchecked((double)Math.Sqrt((double)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
@@ -4386,110 +4421,110 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
- {
- value.register.byte_0 = (Byte)Math.Sqrt(value.register.byte_0);
- value.register.byte_1 = (Byte)Math.Sqrt(value.register.byte_1);
- value.register.byte_2 = (Byte)Math.Sqrt(value.register.byte_2);
- value.register.byte_3 = (Byte)Math.Sqrt(value.register.byte_3);
- value.register.byte_4 = (Byte)Math.Sqrt(value.register.byte_4);
- value.register.byte_5 = (Byte)Math.Sqrt(value.register.byte_5);
- value.register.byte_6 = (Byte)Math.Sqrt(value.register.byte_6);
- value.register.byte_7 = (Byte)Math.Sqrt(value.register.byte_7);
- value.register.byte_8 = (Byte)Math.Sqrt(value.register.byte_8);
- value.register.byte_9 = (Byte)Math.Sqrt(value.register.byte_9);
- value.register.byte_10 = (Byte)Math.Sqrt(value.register.byte_10);
- value.register.byte_11 = (Byte)Math.Sqrt(value.register.byte_11);
- value.register.byte_12 = (Byte)Math.Sqrt(value.register.byte_12);
- value.register.byte_13 = (Byte)Math.Sqrt(value.register.byte_13);
- value.register.byte_14 = (Byte)Math.Sqrt(value.register.byte_14);
- value.register.byte_15 = (Byte)Math.Sqrt(value.register.byte_15);
+ if (typeof(T) == typeof(byte))
+ {
+ value.register.byte_0 = (byte)Math.Sqrt(value.register.byte_0);
+ value.register.byte_1 = (byte)Math.Sqrt(value.register.byte_1);
+ value.register.byte_2 = (byte)Math.Sqrt(value.register.byte_2);
+ value.register.byte_3 = (byte)Math.Sqrt(value.register.byte_3);
+ value.register.byte_4 = (byte)Math.Sqrt(value.register.byte_4);
+ value.register.byte_5 = (byte)Math.Sqrt(value.register.byte_5);
+ value.register.byte_6 = (byte)Math.Sqrt(value.register.byte_6);
+ value.register.byte_7 = (byte)Math.Sqrt(value.register.byte_7);
+ value.register.byte_8 = (byte)Math.Sqrt(value.register.byte_8);
+ value.register.byte_9 = (byte)Math.Sqrt(value.register.byte_9);
+ value.register.byte_10 = (byte)Math.Sqrt(value.register.byte_10);
+ value.register.byte_11 = (byte)Math.Sqrt(value.register.byte_11);
+ value.register.byte_12 = (byte)Math.Sqrt(value.register.byte_12);
+ value.register.byte_13 = (byte)Math.Sqrt(value.register.byte_13);
+ value.register.byte_14 = (byte)Math.Sqrt(value.register.byte_14);
+ value.register.byte_15 = (byte)Math.Sqrt(value.register.byte_15);
return value;
}
- else if (typeof(T) == typeof(SByte))
- {
- value.register.sbyte_0 = (SByte)Math.Sqrt(value.register.sbyte_0);
- value.register.sbyte_1 = (SByte)Math.Sqrt(value.register.sbyte_1);
- value.register.sbyte_2 = (SByte)Math.Sqrt(value.register.sbyte_2);
- value.register.sbyte_3 = (SByte)Math.Sqrt(value.register.sbyte_3);
- value.register.sbyte_4 = (SByte)Math.Sqrt(value.register.sbyte_4);
- value.register.sbyte_5 = (SByte)Math.Sqrt(value.register.sbyte_5);
- value.register.sbyte_6 = (SByte)Math.Sqrt(value.register.sbyte_6);
- value.register.sbyte_7 = (SByte)Math.Sqrt(value.register.sbyte_7);
- value.register.sbyte_8 = (SByte)Math.Sqrt(value.register.sbyte_8);
- value.register.sbyte_9 = (SByte)Math.Sqrt(value.register.sbyte_9);
- value.register.sbyte_10 = (SByte)Math.Sqrt(value.register.sbyte_10);
- value.register.sbyte_11 = (SByte)Math.Sqrt(value.register.sbyte_11);
- value.register.sbyte_12 = (SByte)Math.Sqrt(value.register.sbyte_12);
- value.register.sbyte_13 = (SByte)Math.Sqrt(value.register.sbyte_13);
- value.register.sbyte_14 = (SByte)Math.Sqrt(value.register.sbyte_14);
- value.register.sbyte_15 = (SByte)Math.Sqrt(value.register.sbyte_15);
+ else if (typeof(T) == typeof(sbyte))
+ {
+ value.register.sbyte_0 = (sbyte)Math.Sqrt(value.register.sbyte_0);
+ value.register.sbyte_1 = (sbyte)Math.Sqrt(value.register.sbyte_1);
+ value.register.sbyte_2 = (sbyte)Math.Sqrt(value.register.sbyte_2);
+ value.register.sbyte_3 = (sbyte)Math.Sqrt(value.register.sbyte_3);
+ value.register.sbyte_4 = (sbyte)Math.Sqrt(value.register.sbyte_4);
+ value.register.sbyte_5 = (sbyte)Math.Sqrt(value.register.sbyte_5);
+ value.register.sbyte_6 = (sbyte)Math.Sqrt(value.register.sbyte_6);
+ value.register.sbyte_7 = (sbyte)Math.Sqrt(value.register.sbyte_7);
+ value.register.sbyte_8 = (sbyte)Math.Sqrt(value.register.sbyte_8);
+ value.register.sbyte_9 = (sbyte)Math.Sqrt(value.register.sbyte_9);
+ value.register.sbyte_10 = (sbyte)Math.Sqrt(value.register.sbyte_10);
+ value.register.sbyte_11 = (sbyte)Math.Sqrt(value.register.sbyte_11);
+ value.register.sbyte_12 = (sbyte)Math.Sqrt(value.register.sbyte_12);
+ value.register.sbyte_13 = (sbyte)Math.Sqrt(value.register.sbyte_13);
+ value.register.sbyte_14 = (sbyte)Math.Sqrt(value.register.sbyte_14);
+ value.register.sbyte_15 = (sbyte)Math.Sqrt(value.register.sbyte_15);
return value;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- value.register.uint16_0 = (UInt16)Math.Sqrt(value.register.uint16_0);
- value.register.uint16_1 = (UInt16)Math.Sqrt(value.register.uint16_1);
- value.register.uint16_2 = (UInt16)Math.Sqrt(value.register.uint16_2);
- value.register.uint16_3 = (UInt16)Math.Sqrt(value.register.uint16_3);
- value.register.uint16_4 = (UInt16)Math.Sqrt(value.register.uint16_4);
- value.register.uint16_5 = (UInt16)Math.Sqrt(value.register.uint16_5);
- value.register.uint16_6 = (UInt16)Math.Sqrt(value.register.uint16_6);
- value.register.uint16_7 = (UInt16)Math.Sqrt(value.register.uint16_7);
+ value.register.uint16_0 = (ushort)Math.Sqrt(value.register.uint16_0);
+ value.register.uint16_1 = (ushort)Math.Sqrt(value.register.uint16_1);
+ value.register.uint16_2 = (ushort)Math.Sqrt(value.register.uint16_2);
+ value.register.uint16_3 = (ushort)Math.Sqrt(value.register.uint16_3);
+ value.register.uint16_4 = (ushort)Math.Sqrt(value.register.uint16_4);
+ value.register.uint16_5 = (ushort)Math.Sqrt(value.register.uint16_5);
+ value.register.uint16_6 = (ushort)Math.Sqrt(value.register.uint16_6);
+ value.register.uint16_7 = (ushort)Math.Sqrt(value.register.uint16_7);
return value;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- value.register.int16_0 = (Int16)Math.Sqrt(value.register.int16_0);
- value.register.int16_1 = (Int16)Math.Sqrt(value.register.int16_1);
- value.register.int16_2 = (Int16)Math.Sqrt(value.register.int16_2);
- value.register.int16_3 = (Int16)Math.Sqrt(value.register.int16_3);
- value.register.int16_4 = (Int16)Math.Sqrt(value.register.int16_4);
- value.register.int16_5 = (Int16)Math.Sqrt(value.register.int16_5);
- value.register.int16_6 = (Int16)Math.Sqrt(value.register.int16_6);
- value.register.int16_7 = (Int16)Math.Sqrt(value.register.int16_7);
+ value.register.int16_0 = (short)Math.Sqrt(value.register.int16_0);
+ value.register.int16_1 = (short)Math.Sqrt(value.register.int16_1);
+ value.register.int16_2 = (short)Math.Sqrt(value.register.int16_2);
+ value.register.int16_3 = (short)Math.Sqrt(value.register.int16_3);
+ value.register.int16_4 = (short)Math.Sqrt(value.register.int16_4);
+ value.register.int16_5 = (short)Math.Sqrt(value.register.int16_5);
+ value.register.int16_6 = (short)Math.Sqrt(value.register.int16_6);
+ value.register.int16_7 = (short)Math.Sqrt(value.register.int16_7);
return value;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- value.register.uint32_0 = (UInt32)Math.Sqrt(value.register.uint32_0);
- value.register.uint32_1 = (UInt32)Math.Sqrt(value.register.uint32_1);
- value.register.uint32_2 = (UInt32)Math.Sqrt(value.register.uint32_2);
- value.register.uint32_3 = (UInt32)Math.Sqrt(value.register.uint32_3);
+ value.register.uint32_0 = (uint)Math.Sqrt(value.register.uint32_0);
+ value.register.uint32_1 = (uint)Math.Sqrt(value.register.uint32_1);
+ value.register.uint32_2 = (uint)Math.Sqrt(value.register.uint32_2);
+ value.register.uint32_3 = (uint)Math.Sqrt(value.register.uint32_3);
return value;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- value.register.int32_0 = (Int32)Math.Sqrt(value.register.int32_0);
- value.register.int32_1 = (Int32)Math.Sqrt(value.register.int32_1);
- value.register.int32_2 = (Int32)Math.Sqrt(value.register.int32_2);
- value.register.int32_3 = (Int32)Math.Sqrt(value.register.int32_3);
+ value.register.int32_0 = (int)Math.Sqrt(value.register.int32_0);
+ value.register.int32_1 = (int)Math.Sqrt(value.register.int32_1);
+ value.register.int32_2 = (int)Math.Sqrt(value.register.int32_2);
+ value.register.int32_3 = (int)Math.Sqrt(value.register.int32_3);
return value;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- value.register.uint64_0 = (UInt64)Math.Sqrt(value.register.uint64_0);
- value.register.uint64_1 = (UInt64)Math.Sqrt(value.register.uint64_1);
+ value.register.uint64_0 = (ulong)Math.Sqrt(value.register.uint64_0);
+ value.register.uint64_1 = (ulong)Math.Sqrt(value.register.uint64_1);
return value;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- value.register.int64_0 = (Int64)Math.Sqrt(value.register.int64_0);
- value.register.int64_1 = (Int64)Math.Sqrt(value.register.int64_1);
+ value.register.int64_0 = (long)Math.Sqrt(value.register.int64_0);
+ value.register.int64_1 = (long)Math.Sqrt(value.register.int64_1);
return value;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- value.register.single_0 = (Single)Math.Sqrt(value.register.single_0);
- value.register.single_1 = (Single)Math.Sqrt(value.register.single_1);
- value.register.single_2 = (Single)Math.Sqrt(value.register.single_2);
- value.register.single_3 = (Single)Math.Sqrt(value.register.single_3);
+ value.register.single_0 = (float)Math.Sqrt(value.register.single_0);
+ value.register.single_1 = (float)Math.Sqrt(value.register.single_1);
+ value.register.single_2 = (float)Math.Sqrt(value.register.single_2);
+ value.register.single_3 = (float)Math.Sqrt(value.register.single_3);
return value;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- value.register.double_0 = (Double)Math.Sqrt(value.register.double_0);
- value.register.double_1 = (Double)Math.Sqrt(value.register.double_1);
+ value.register.double_0 = (double)Math.Sqrt(value.register.double_0);
+ value.register.double_1 = (double)Math.Sqrt(value.register.double_1);
return value;
}
else
@@ -4504,45 +4539,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarEquals(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (Byte)(object)left == (Byte)(object)right;
+ return (byte)(object)left == (byte)(object)right;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (SByte)(object)left == (SByte)(object)right;
+ return (sbyte)(object)left == (sbyte)(object)right;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (UInt16)(object)left == (UInt16)(object)right;
+ return (ushort)(object)left == (ushort)(object)right;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (Int16)(object)left == (Int16)(object)right;
+ return (short)(object)left == (short)(object)right;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (UInt32)(object)left == (UInt32)(object)right;
+ return (uint)(object)left == (uint)(object)right;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (Int32)(object)left == (Int32)(object)right;
+ return (int)(object)left == (int)(object)right;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (UInt64)(object)left == (UInt64)(object)right;
+ return (ulong)(object)left == (ulong)(object)right;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (Int64)(object)left == (Int64)(object)right;
+ return (long)(object)left == (long)(object)right;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (Single)(object)left == (Single)(object)right;
+ return (float)(object)left == (float)(object)right;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (Double)(object)left == (Double)(object)right;
+ return (double)(object)left == (double)(object)right;
}
else
{
@@ -4553,45 +4588,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarLessThan(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (Byte)(object)left < (Byte)(object)right;
+ return (byte)(object)left < (byte)(object)right;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (SByte)(object)left < (SByte)(object)right;
+ return (sbyte)(object)left < (sbyte)(object)right;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (UInt16)(object)left < (UInt16)(object)right;
+ return (ushort)(object)left < (ushort)(object)right;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (Int16)(object)left < (Int16)(object)right;
+ return (short)(object)left < (short)(object)right;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (UInt32)(object)left < (UInt32)(object)right;
+ return (uint)(object)left < (uint)(object)right;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (Int32)(object)left < (Int32)(object)right;
+ return (int)(object)left < (int)(object)right;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (UInt64)(object)left < (UInt64)(object)right;
+ return (ulong)(object)left < (ulong)(object)right;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (Int64)(object)left < (Int64)(object)right;
+ return (long)(object)left < (long)(object)right;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (Single)(object)left < (Single)(object)right;
+ return (float)(object)left < (float)(object)right;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (Double)(object)left < (Double)(object)right;
+ return (double)(object)left < (double)(object)right;
}
else
{
@@ -4602,45 +4637,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarGreaterThan(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (Byte)(object)left > (Byte)(object)right;
+ return (byte)(object)left > (byte)(object)right;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (SByte)(object)left > (SByte)(object)right;
+ return (sbyte)(object)left > (sbyte)(object)right;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (UInt16)(object)left > (UInt16)(object)right;
+ return (ushort)(object)left > (ushort)(object)right;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (Int16)(object)left > (Int16)(object)right;
+ return (short)(object)left > (short)(object)right;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (UInt32)(object)left > (UInt32)(object)right;
+ return (uint)(object)left > (uint)(object)right;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (Int32)(object)left > (Int32)(object)right;
+ return (int)(object)left > (int)(object)right;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (UInt64)(object)left > (UInt64)(object)right;
+ return (ulong)(object)left > (ulong)(object)right;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (Int64)(object)left > (Int64)(object)right;
+ return (long)(object)left > (long)(object)right;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (Single)(object)left > (Single)(object)right;
+ return (float)(object)left > (float)(object)right;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (Double)(object)left > (Double)(object)right;
+ return (double)(object)left > (double)(object)right;
}
else
{
@@ -4651,45 +4686,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarAdd(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)unchecked((Byte)((Byte)(object)left + (Byte)(object)right));
+ return (T)(object)unchecked((byte)((byte)(object)left + (byte)(object)right));
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)unchecked((SByte)((SByte)(object)left + (SByte)(object)right));
+ return (T)(object)unchecked((sbyte)((sbyte)(object)left + (sbyte)(object)right));
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)unchecked((UInt16)((UInt16)(object)left + (UInt16)(object)right));
+ return (T)(object)unchecked((ushort)((ushort)(object)left + (ushort)(object)right));
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)unchecked((Int16)((Int16)(object)left + (Int16)(object)right));
+ return (T)(object)unchecked((short)((short)(object)left + (short)(object)right));
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)unchecked((UInt32)((UInt32)(object)left + (UInt32)(object)right));
+ return (T)(object)unchecked((uint)((uint)(object)left + (uint)(object)right));
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)unchecked((Int32)((Int32)(object)left + (Int32)(object)right));
+ return (T)(object)unchecked((int)((int)(object)left + (int)(object)right));
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)unchecked((UInt64)((UInt64)(object)left + (UInt64)(object)right));
+ return (T)(object)unchecked((ulong)((ulong)(object)left + (ulong)(object)right));
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)unchecked((Int64)((Int64)(object)left + (Int64)(object)right));
+ return (T)(object)unchecked((long)((long)(object)left + (long)(object)right));
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)unchecked((Single)((Single)(object)left + (Single)(object)right));
+ return (T)(object)unchecked((float)((float)(object)left + (float)(object)right));
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)unchecked((Double)((Double)(object)left + (Double)(object)right));
+ return (T)(object)unchecked((double)((double)(object)left + (double)(object)right));
}
else
{
@@ -4700,45 +4735,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarSubtract(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)(Byte)((Byte)(object)left - (Byte)(object)right);
+ return (T)(object)(byte)((byte)(object)left - (byte)(object)right);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)(SByte)((SByte)(object)left - (SByte)(object)right);
+ return (T)(object)(sbyte)((sbyte)(object)left - (sbyte)(object)right);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)(UInt16)((UInt16)(object)left - (UInt16)(object)right);
+ return (T)(object)(ushort)((ushort)(object)left - (ushort)(object)right);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)(Int16)((Int16)(object)left - (Int16)(object)right);
+ return (T)(object)(short)((short)(object)left - (short)(object)right);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)(UInt32)((UInt32)(object)left - (UInt32)(object)right);
+ return (T)(object)(uint)((uint)(object)left - (uint)(object)right);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)(Int32)((Int32)(object)left - (Int32)(object)right);
+ return (T)(object)(int)((int)(object)left - (int)(object)right);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)(UInt64)((UInt64)(object)left - (UInt64)(object)right);
+ return (T)(object)(ulong)((ulong)(object)left - (ulong)(object)right);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)(Int64)((Int64)(object)left - (Int64)(object)right);
+ return (T)(object)(long)((long)(object)left - (long)(object)right);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)(Single)((Single)(object)left - (Single)(object)right);
+ return (T)(object)(float)((float)(object)left - (float)(object)right);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)(Double)((Double)(object)left - (Double)(object)right);
+ return (T)(object)(double)((double)(object)left - (double)(object)right);
}
else
{
@@ -4749,45 +4784,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarMultiply(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)unchecked((Byte)((Byte)(object)left * (Byte)(object)right));
+ return (T)(object)unchecked((byte)((byte)(object)left * (byte)(object)right));
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)unchecked((SByte)((SByte)(object)left * (SByte)(object)right));
+ return (T)(object)unchecked((sbyte)((sbyte)(object)left * (sbyte)(object)right));
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)unchecked((UInt16)((UInt16)(object)left * (UInt16)(object)right));
+ return (T)(object)unchecked((ushort)((ushort)(object)left * (ushort)(object)right));
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)unchecked((Int16)((Int16)(object)left * (Int16)(object)right));
+ return (T)(object)unchecked((short)((short)(object)left * (short)(object)right));
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)unchecked((UInt32)((UInt32)(object)left * (UInt32)(object)right));
+ return (T)(object)unchecked((uint)((uint)(object)left * (uint)(object)right));
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)unchecked((Int32)((Int32)(object)left * (Int32)(object)right));
+ return (T)(object)unchecked((int)((int)(object)left * (int)(object)right));
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)unchecked((UInt64)((UInt64)(object)left * (UInt64)(object)right));
+ return (T)(object)unchecked((ulong)((ulong)(object)left * (ulong)(object)right));
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)unchecked((Int64)((Int64)(object)left * (Int64)(object)right));
+ return (T)(object)unchecked((long)((long)(object)left * (long)(object)right));
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)unchecked((Single)((Single)(object)left * (Single)(object)right));
+ return (T)(object)unchecked((float)((float)(object)left * (float)(object)right));
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)unchecked((Double)((Double)(object)left * (Double)(object)right));
+ return (T)(object)unchecked((double)((double)(object)left * (double)(object)right));
}
else
{
@@ -4798,45 +4833,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarDivide(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)(Byte)((Byte)(object)left / (Byte)(object)right);
+ return (T)(object)(byte)((byte)(object)left / (byte)(object)right);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)(SByte)((SByte)(object)left / (SByte)(object)right);
+ return (T)(object)(sbyte)((sbyte)(object)left / (sbyte)(object)right);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)(UInt16)((UInt16)(object)left / (UInt16)(object)right);
+ return (T)(object)(ushort)((ushort)(object)left / (ushort)(object)right);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)(Int16)((Int16)(object)left / (Int16)(object)right);
+ return (T)(object)(short)((short)(object)left / (short)(object)right);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)(UInt32)((UInt32)(object)left / (UInt32)(object)right);
+ return (T)(object)(uint)((uint)(object)left / (uint)(object)right);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)(Int32)((Int32)(object)left / (Int32)(object)right);
+ return (T)(object)(int)((int)(object)left / (int)(object)right);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)(UInt64)((UInt64)(object)left / (UInt64)(object)right);
+ return (T)(object)(ulong)((ulong)(object)left / (ulong)(object)right);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)(Int64)((Int64)(object)left / (Int64)(object)right);
+ return (T)(object)(long)((long)(object)left / (long)(object)right);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)(Single)((Single)(object)left / (Single)(object)right);
+ return (T)(object)(float)((float)(object)left / (float)(object)right);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)(Double)((Double)(object)left / (Double)(object)right);
+ return (T)(object)(double)((double)(object)left / (double)(object)right);
}
else
{
@@ -4847,54 +4882,54 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetOneValue()
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte value = 1;
+ byte value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte value = 1;
+ sbyte value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16 value = 1;
+ ushort value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16 value = 1;
+ short value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32 value = 1;
+ uint value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32 value = 1;
+ int value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64 value = 1;
+ ulong value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64 value = 1;
+ long value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single value = 1;
+ float value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double value = 1;
+ double value = 1;
return (T)(object)value;
}
else
@@ -4906,43 +4941,43 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetAllBitsSetValue()
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
return (T)(object)ConstantHelper.GetByteWithAllBitsSet();
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
return (T)(object)ConstantHelper.GetSByteWithAllBitsSet();
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
return (T)(object)ConstantHelper.GetUInt16WithAllBitsSet();
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
return (T)(object)ConstantHelper.GetInt16WithAllBitsSet();
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
return (T)(object)ConstantHelper.GetUInt32WithAllBitsSet();
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
return (T)(object)ConstantHelper.GetInt32WithAllBitsSet();
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
return (T)(object)ConstantHelper.GetUInt64WithAllBitsSet();
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
return (T)(object)ConstantHelper.GetInt64WithAllBitsSet();
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
return (T)(object)ConstantHelper.GetSingleWithAllBitsSet();
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
return (T)(object)ConstantHelper.GetDoubleWithAllBitsSet();
}
@@ -4966,22 +5001,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<Byte> source, out Vector<UInt16> low, out Vector<UInt16> high)
+ public static unsafe void Widen(Vector<byte> source, out Vector<ushort> low, out Vector<ushort> high)
{
- int elements = Vector<Byte>.Count;
- UInt16* lowPtr = stackalloc UInt16[elements / 2];
+ int elements = Vector<byte>.Count;
+ ushort* lowPtr = stackalloc ushort[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (UInt16)source[i];
+ lowPtr[i] = (ushort)source[i];
}
- UInt16* highPtr = stackalloc UInt16[elements / 2];
+ ushort* highPtr = stackalloc ushort[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (UInt16)source[i + (elements / 2)];
+ highPtr[i] = (ushort)source[i + (elements / 2)];
}
- low = new Vector<UInt16>(lowPtr);
- high = new Vector<UInt16>(highPtr);
+ low = new Vector<ushort>(lowPtr);
+ high = new Vector<ushort>(highPtr);
}
/// <summary>
@@ -4992,22 +5027,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<UInt16> source, out Vector<UInt32> low, out Vector<UInt32> high)
+ public static unsafe void Widen(Vector<ushort> source, out Vector<uint> low, out Vector<uint> high)
{
- int elements = Vector<UInt16>.Count;
- UInt32* lowPtr = stackalloc UInt32[elements / 2];
+ int elements = Vector<ushort>.Count;
+ uint* lowPtr = stackalloc uint[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (UInt32)source[i];
+ lowPtr[i] = (uint)source[i];
}
- UInt32* highPtr = stackalloc UInt32[elements / 2];
+ uint* highPtr = stackalloc uint[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (UInt32)source[i + (elements / 2)];
+ highPtr[i] = (uint)source[i + (elements / 2)];
}
- low = new Vector<UInt32>(lowPtr);
- high = new Vector<UInt32>(highPtr);
+ low = new Vector<uint>(lowPtr);
+ high = new Vector<uint>(highPtr);
}
/// <summary>
@@ -5018,22 +5053,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<UInt32> source, out Vector<UInt64> low, out Vector<UInt64> high)
+ public static unsafe void Widen(Vector<uint> source, out Vector<ulong> low, out Vector<ulong> high)
{
- int elements = Vector<UInt32>.Count;
- UInt64* lowPtr = stackalloc UInt64[elements / 2];
+ int elements = Vector<uint>.Count;
+ ulong* lowPtr = stackalloc ulong[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (UInt64)source[i];
+ lowPtr[i] = (ulong)source[i];
}
- UInt64* highPtr = stackalloc UInt64[elements / 2];
+ ulong* highPtr = stackalloc ulong[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (UInt64)source[i + (elements / 2)];
+ highPtr[i] = (ulong)source[i + (elements / 2)];
}
- low = new Vector<UInt64>(lowPtr);
- high = new Vector<UInt64>(highPtr);
+ low = new Vector<ulong>(lowPtr);
+ high = new Vector<ulong>(highPtr);
}
/// <summary>
@@ -5044,22 +5079,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<SByte> source, out Vector<Int16> low, out Vector<Int16> high)
+ public static unsafe void Widen(Vector<sbyte> source, out Vector<short> low, out Vector<short> high)
{
- int elements = Vector<SByte>.Count;
- Int16* lowPtr = stackalloc Int16[elements / 2];
+ int elements = Vector<sbyte>.Count;
+ short* lowPtr = stackalloc short[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Int16)source[i];
+ lowPtr[i] = (short)source[i];
}
- Int16* highPtr = stackalloc Int16[elements / 2];
+ short* highPtr = stackalloc short[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Int16)source[i + (elements / 2)];
+ highPtr[i] = (short)source[i + (elements / 2)];
}
- low = new Vector<Int16>(lowPtr);
- high = new Vector<Int16>(highPtr);
+ low = new Vector<short>(lowPtr);
+ high = new Vector<short>(highPtr);
}
/// <summary>
@@ -5069,22 +5104,22 @@ namespace System.Numerics
/// <param name="high">The second output vector, whose elements will contain the widened elements from higher indices in the source vector.</param>
/// </summary>
[Intrinsic]
- public static unsafe void Widen(Vector<Int16> source, out Vector<Int32> low, out Vector<Int32> high)
+ public static unsafe void Widen(Vector<short> source, out Vector<int> low, out Vector<int> high)
{
- int elements = Vector<Int16>.Count;
- Int32* lowPtr = stackalloc Int32[elements / 2];
+ int elements = Vector<short>.Count;
+ int* lowPtr = stackalloc int[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Int32)source[i];
+ lowPtr[i] = (int)source[i];
}
- Int32* highPtr = stackalloc Int32[elements / 2];
+ int* highPtr = stackalloc int[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Int32)source[i + (elements / 2)];
+ highPtr[i] = (int)source[i + (elements / 2)];
}
- low = new Vector<Int32>(lowPtr);
- high = new Vector<Int32>(highPtr);
+ low = new Vector<int>(lowPtr);
+ high = new Vector<int>(highPtr);
}
/// <summary>
@@ -5094,22 +5129,22 @@ namespace System.Numerics
/// <param name="high">The second output vector, whose elements will contain the widened elements from higher indices in the source vector.</param>
/// </summary>
[Intrinsic]
- public static unsafe void Widen(Vector<Int32> source, out Vector<Int64> low, out Vector<Int64> high)
+ public static unsafe void Widen(Vector<int> source, out Vector<long> low, out Vector<long> high)
{
- int elements = Vector<Int32>.Count;
- Int64* lowPtr = stackalloc Int64[elements / 2];
+ int elements = Vector<int>.Count;
+ long* lowPtr = stackalloc long[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Int64)source[i];
+ lowPtr[i] = (long)source[i];
}
- Int64* highPtr = stackalloc Int64[elements / 2];
+ long* highPtr = stackalloc long[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Int64)source[i + (elements / 2)];
+ highPtr[i] = (long)source[i + (elements / 2)];
}
- low = new Vector<Int64>(lowPtr);
- high = new Vector<Int64>(highPtr);
+ low = new Vector<long>(lowPtr);
+ high = new Vector<long>(highPtr);
}
/// <summary>
@@ -5119,22 +5154,22 @@ namespace System.Numerics
/// <param name="high">The second output vector, whose elements will contain the widened elements from higher indices in the source vector.</param>
/// </summary>
[Intrinsic]
- public static unsafe void Widen(Vector<Single> source, out Vector<Double> low, out Vector<Double> high)
+ public static unsafe void Widen(Vector<float> source, out Vector<double> low, out Vector<double> high)
{
- int elements = Vector<Single>.Count;
- Double* lowPtr = stackalloc Double[elements / 2];
+ int elements = Vector<float>.Count;
+ double* lowPtr = stackalloc double[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Double)source[i];
+ lowPtr[i] = (double)source[i];
}
- Double* highPtr = stackalloc Double[elements / 2];
+ double* highPtr = stackalloc double[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Double)source[i + (elements / 2)];
+ highPtr[i] = (double)source[i + (elements / 2)];
}
- low = new Vector<Double>(lowPtr);
- high = new Vector<Double>(highPtr);
+ low = new Vector<double>(lowPtr);
+ high = new Vector<double>(highPtr);
}
/// <summary>
@@ -5145,23 +5180,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<Byte> Narrow(Vector<UInt16> low, Vector<UInt16> high)
+ public static unsafe Vector<byte> Narrow(Vector<ushort> low, Vector<ushort> high)
{
- unchecked
- {
- int elements = Vector<Byte>.Count;
- Byte* retPtr = stackalloc Byte[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Byte)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Byte)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<byte>.Count;
+ byte* retPtr = stackalloc byte[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (byte)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (byte)high[i];
+ }
- return new Vector<Byte>(retPtr);
- }
+ return new Vector<byte>(retPtr);
+ }
}
/// <summary>
@@ -5172,23 +5207,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt16> Narrow(Vector<UInt32> low, Vector<UInt32> high)
+ public static unsafe Vector<ushort> Narrow(Vector<uint> low, Vector<uint> high)
{
- unchecked
- {
- int elements = Vector<UInt16>.Count;
- UInt16* retPtr = stackalloc UInt16[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (UInt16)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (UInt16)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<ushort>.Count;
+ ushort* retPtr = stackalloc ushort[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (ushort)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (ushort)high[i];
+ }
- return new Vector<UInt16>(retPtr);
- }
+ return new Vector<ushort>(retPtr);
+ }
}
/// <summary>
@@ -5199,23 +5234,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt32> Narrow(Vector<UInt64> low, Vector<UInt64> high)
+ public static unsafe Vector<uint> Narrow(Vector<ulong> low, Vector<ulong> high)
{
- unchecked
- {
- int elements = Vector<UInt32>.Count;
- UInt32* retPtr = stackalloc UInt32[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (UInt32)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (UInt32)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<uint>.Count;
+ uint* retPtr = stackalloc uint[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (uint)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (uint)high[i];
+ }
- return new Vector<UInt32>(retPtr);
- }
+ return new Vector<uint>(retPtr);
+ }
}
/// <summary>
@@ -5226,23 +5261,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<SByte> Narrow(Vector<Int16> low, Vector<Int16> high)
+ public static unsafe Vector<sbyte> Narrow(Vector<short> low, Vector<short> high)
{
- unchecked
- {
- int elements = Vector<SByte>.Count;
- SByte* retPtr = stackalloc SByte[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (SByte)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (SByte)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<sbyte>.Count;
+ sbyte* retPtr = stackalloc sbyte[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (sbyte)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (sbyte)high[i];
+ }
- return new Vector<SByte>(retPtr);
- }
+ return new Vector<sbyte>(retPtr);
+ }
}
/// <summary>
@@ -5252,23 +5287,23 @@ namespace System.Numerics
/// <returns>A Vector{Int16} containing elements narrowed from the source vectors.</returns>
/// </summary>
[Intrinsic]
- public static unsafe Vector<Int16> Narrow(Vector<Int32> low, Vector<Int32> high)
+ public static unsafe Vector<short> Narrow(Vector<int> low, Vector<int> high)
{
- unchecked
- {
- int elements = Vector<Int16>.Count;
- Int16* retPtr = stackalloc Int16[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Int16)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Int16)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<short>.Count;
+ short* retPtr = stackalloc short[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (short)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (short)high[i];
+ }
- return new Vector<Int16>(retPtr);
- }
+ return new Vector<short>(retPtr);
+ }
}
/// <summary>
@@ -5278,23 +5313,23 @@ namespace System.Numerics
/// <returns>A Vector{Int32} containing elements narrowed from the source vectors.</returns>
/// </summary>
[Intrinsic]
- public static unsafe Vector<Int32> Narrow(Vector<Int64> low, Vector<Int64> high)
+ public static unsafe Vector<int> Narrow(Vector<long> low, Vector<long> high)
{
- unchecked
- {
- int elements = Vector<Int32>.Count;
- Int32* retPtr = stackalloc Int32[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Int32)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Int32)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<int>.Count;
+ int* retPtr = stackalloc int[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (int)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (int)high[i];
+ }
- return new Vector<Int32>(retPtr);
- }
+ return new Vector<int>(retPtr);
+ }
}
/// <summary>
@@ -5304,23 +5339,23 @@ namespace System.Numerics
/// <returns>A Vector{Single} containing elements narrowed from the source vectors.</returns>
/// </summary>
[Intrinsic]
- public static unsafe Vector<Single> Narrow(Vector<Double> low, Vector<Double> high)
+ public static unsafe Vector<float> Narrow(Vector<double> low, Vector<double> high)
{
- unchecked
- {
- int elements = Vector<Single>.Count;
- Single* retPtr = stackalloc Single[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Single)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Single)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<float>.Count;
+ float* retPtr = stackalloc float[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (float)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (float)high[i];
+ }
- return new Vector<Single>(retPtr);
- }
+ return new Vector<float>(retPtr);
+ }
}
#endregion Widen/Narrow
@@ -5332,19 +5367,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Single> ConvertToSingle(Vector<Int32> value)
+ public static unsafe Vector<float> ConvertToSingle(Vector<int> value)
{
- unchecked
- {
- int elements = Vector<Single>.Count;
- Single* retPtr = stackalloc Single[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Single)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<float>.Count;
+ float* retPtr = stackalloc float[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (float)value[i];
+ }
- return new Vector<Single>(retPtr);
- }
+ return new Vector<float>(retPtr);
+ }
}
/// <summary>
@@ -5354,19 +5389,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<Single> ConvertToSingle(Vector<UInt32> value)
+ public static unsafe Vector<float> ConvertToSingle(Vector<uint> value)
{
- unchecked
- {
- int elements = Vector<Single>.Count;
- Single* retPtr = stackalloc Single[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Single)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<float>.Count;
+ float* retPtr = stackalloc float[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (float)value[i];
+ }
- return new Vector<Single>(retPtr);
- }
+ return new Vector<float>(retPtr);
+ }
}
/// <summary>
@@ -5375,19 +5410,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Double> ConvertToDouble(Vector<Int64> value)
+ public static unsafe Vector<double> ConvertToDouble(Vector<long> value)
{
- unchecked
- {
- int elements = Vector<Double>.Count;
- Double* retPtr = stackalloc Double[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Double)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<double>.Count;
+ double* retPtr = stackalloc double[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (double)value[i];
+ }
- return new Vector<Double>(retPtr);
- }
+ return new Vector<double>(retPtr);
+ }
}
/// <summary>
@@ -5397,19 +5432,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<Double> ConvertToDouble(Vector<UInt64> value)
+ public static unsafe Vector<double> ConvertToDouble(Vector<ulong> value)
{
- unchecked
- {
- int elements = Vector<Double>.Count;
- Double* retPtr = stackalloc Double[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Double)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<double>.Count;
+ double* retPtr = stackalloc double[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (double)value[i];
+ }
- return new Vector<Double>(retPtr);
- }
+ return new Vector<double>(retPtr);
+ }
}
/// <summary>
@@ -5418,19 +5453,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Int32> ConvertToInt32(Vector<Single> value)
+ public static unsafe Vector<int> ConvertToInt32(Vector<float> value)
{
- unchecked
- {
- int elements = Vector<Int32>.Count;
- Int32* retPtr = stackalloc Int32[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Int32)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<int>.Count;
+ int* retPtr = stackalloc int[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (int)value[i];
+ }
- return new Vector<Int32>(retPtr);
- }
+ return new Vector<int>(retPtr);
+ }
}
/// <summary>
@@ -5440,19 +5475,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt32> ConvertToUInt32(Vector<Single> value)
+ public static unsafe Vector<uint> ConvertToUInt32(Vector<float> value)
{
- unchecked
- {
- int elements = Vector<UInt32>.Count;
- UInt32* retPtr = stackalloc UInt32[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (UInt32)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<uint>.Count;
+ uint* retPtr = stackalloc uint[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (uint)value[i];
+ }
- return new Vector<UInt32>(retPtr);
- }
+ return new Vector<uint>(retPtr);
+ }
}
/// <summary>
@@ -5461,19 +5496,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Int64> ConvertToInt64(Vector<Double> value)
+ public static unsafe Vector<long> ConvertToInt64(Vector<double> value)
{
- unchecked
- {
- int elements = Vector<Int64>.Count;
- Int64* retPtr = stackalloc Int64[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Int64)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<long>.Count;
+ long* retPtr = stackalloc long[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (long)value[i];
+ }
- return new Vector<Int64>(retPtr);
- }
+ return new Vector<long>(retPtr);
+ }
}
/// <summary>
@@ -5483,19 +5518,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt64> ConvertToUInt64(Vector<Double> value)
+ public static unsafe Vector<ulong> ConvertToUInt64(Vector<double> value)
{
- unchecked
- {
- int elements = Vector<UInt64>.Count;
- UInt64* retPtr = stackalloc UInt64[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (UInt64)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<ulong>.Count;
+ ulong* retPtr = stackalloc ulong[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (ulong)value[i];
+ }
- return new Vector<UInt64>(retPtr);
- }
+ return new Vector<ulong>(retPtr);
+ }
}
#endregion Same-Size Conversion
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt b/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt
index 275f47350..9eda34d04 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt
@@ -7,9 +7,13 @@
<#@ import namespace="System.Runtime.InteropServices" #>
<#@ include file="GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #>
+#if netcoreapp
+using Internal.Runtime.CompilerServices;
+#endif
using System.Globalization;
using System.Numerics.Hashing;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
namespace System.Numerics
@@ -17,8 +21,8 @@ namespace System.Numerics
/* Note: The following patterns are used throughout the code here and are described here
*
* PATTERN:
- * if (typeof(T) == typeof(Int32)) { ... }
- * else if (typeof(T) == typeof(Single)) { ... }
+ * if (typeof(T) == typeof(int)) { ... }
+ * else if (typeof(T) == typeof(float)) { ... }
* EXPLANATION:
* At runtime, each instantiation of Vector<T> will be type-specific, and each of these typeof blocks will be eliminated,
* as typeof(T) is a (JIT) compile-time constant for each instantiation. This design was chosen to eliminate any overhead from
@@ -101,7 +105,7 @@ namespace System.Numerics
internal byte _byte;
}
- // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
+ // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
private static unsafe int InitializeCount()
{
VectorSizeHelper vsh;
@@ -110,15 +114,16 @@ namespace System.Numerics
int vectorSizeInBytes = (int)(byteBase - vectorBase);
int typeSizeInBytes = -1;
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- typeSizeInBytes = sizeof(<#=type.Name#>);
+ typeSizeInBytes = sizeof(<#=typeAliases[type]#>);
}
<#
- }
+ }
#>
else
{
@@ -139,41 +144,43 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (<#=type.Name#>)(object)value;
+ *(basePtr + g) = (<#=typeAliases[type]#>)(object)value;
}
}
}
<#
- }
+ }
#>
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < totalSize / Marshal.SizeOf(type); g++)
- {
+ for (int g = 0; g < totalSize / Marshal.SizeOf(type); g++)
+ {
#>
- <#=GetRegisterFieldName(type, g)#> = (<#=type.Name#>)(object)value;
+ <#=GetRegisterFieldName(type, g)#> = (<#=typeAliases[type]#>)(object)value;
<#
- }
+ }
#>
}
<#
- }
+ }
#>
}
}
@@ -198,49 +205,51 @@ namespace System.Numerics
}
if (index < 0 || (values.Length - index) < Count)
{
- throw new IndexOutOfRangeException();
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
}
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (<#=type.Name#>)(object)values[g + index];
+ *(basePtr + g) = (<#=typeAliases[type]#>)(object)values[g + index];
}
}
}
<#
- }
+ }
#>
}
else
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- *(basePtr + <#=g#>) = (<#=type.Name#>)(object)values[<#=g#> + index];
+ *(basePtr + <#=g#>) = (<#=typeAliases[type]#>)(object)values[<#=g#> + index];
<#
- }
+ }
#>
}
}
<#
- }
+ }
#>
}
}
@@ -254,14 +263,15 @@ namespace System.Numerics
internal unsafe Vector(void* dataPointer, int offset)
: this()
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* castedPtr = (<#=type.Name#>*)dataPointer;
+ <#=typeAliases[type]#>* castedPtr = (<#=typeAliases[type]#>*)dataPointer;
castedPtr += offset;
- fixed (<#=type.Name#>* registerBase = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* registerBase = &this.<#=GetRegisterFieldName(type, 0)#>)
{
for (int g = 0; g < Count; g++)
{
@@ -270,7 +280,7 @@ namespace System.Numerics
}
}
<#
- }
+ }
#>
else
{
@@ -283,6 +293,28 @@ namespace System.Numerics
{
this.register = existingRegister;
}
+
+#if netcoreapp
+ /// <summary>
+ /// Constructs a vector from the given span. The span must contain at least Vector'T.Count elements.
+ /// </summary>
+ public Vector(Span<T> values)
+ : this()
+ {
+ <#=GenerateIfConditionAllTypes(supportedTypes)#>
+ {
+ if (values.Length < Count)
+ {
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
+ }
+ this = Unsafe.ReadUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)));
+ }
+ else
+ {
+ throw new NotSupportedException(SR.Arg_TypeNotSupported);
+ }
+ }
+#endif
#endregion Constructors
#region Public Instance Methods
@@ -325,46 +357,48 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=type.Name#>[])(object)destination;
- fixed (<#=type.Name#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
+ <#=typeAliases[type]#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=typeAliases[type]#>[])(object)destination;
+ fixed (<#=typeAliases[type]#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (<#=type.Name#>)(object)this[g];
+ destinationBase[startIndex + g] = (<#=typeAliases[type]#>)(object)this[g];
}
}
}
<#
- }
+ }
#>
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=type.Name#>[])(object)destination;
- fixed (<#=type.Name#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
+ <#=typeAliases[type]#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=typeAliases[type]#>[])(object)destination;
+ fixed (<#=typeAliases[type]#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
destinationBase[startIndex + <#=g#>] = this.<#=GetRegisterFieldName(type, g)#>;
<#
- }
+ }
#>
}
}
<#
- }
+ }
#>
}
}
@@ -381,12 +415,13 @@ namespace System.Numerics
{
throw new IndexOutOfRangeException(SR.Format(SR.Arg_ArgumentOutOfRangeException, index));
}
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
return (T)(object)*(basePtr + index);
}
@@ -437,36 +472,37 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
return
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
<#
- if (g == 0)
- {
+ if (g == 0)
+ {
#>
this.<#=GetRegisterFieldName(type, g)#> == other.<#=GetRegisterFieldName(type, g)#>
<#
- }
- else
- {
+ }
+ else
+ {
#>
&& this.<#=GetRegisterFieldName(type, g)#> == other.<#=GetRegisterFieldName(type, g)#><#=(g == (GetNumFields(type, totalSize) -1)) ? ";" : ""#>
<#
- }
+ }
#>
<#
- }
+ }
#>
}
<#
- }
+ }
#>
else
{
@@ -485,19 +521,20 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((<#=type.Name#>)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((<#=typeAliases[type]#>)(object)this[g]).GetHashCode());
}
return hash;
}
<#
- }
+ }
#>
else
{
@@ -506,23 +543,24 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
hash = HashHelpers.Combine(hash, this.<#=GetRegisterFieldName(type, g)#>.GetHashCode());
<#
- }
+ }
#>
return hash;
}
<#
- }
+ }
#>
else
{
@@ -588,20 +626,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -611,8 +650,9 @@ namespace System.Numerics
else
{
Vector<T> sum = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
@@ -620,13 +660,13 @@ namespace System.Numerics
for (int g = 0; g < GetNumFields(type, totalSize); g++)
{
#>
- sum.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> + right.<#= GetRegisterFieldName(type, g) #>);
+ sum.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> + right.<#= GetRegisterFieldName(type, g) #>);
<#
}
#>
}
<#
- }
+ }
#>
return sum;
}
@@ -645,20 +685,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -668,22 +709,23 @@ namespace System.Numerics
else
{
Vector<T> difference = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- difference.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> - right.<#= GetRegisterFieldName(type, g) #>);
+ difference.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> - right.<#= GetRegisterFieldName(type, g) #>);
<#
- }
+ }
#>
}
<#
- }
+ }
#>
return difference;
}
@@ -703,20 +745,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -726,18 +769,19 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> * right.<#= GetRegisterFieldName(type, g) #>);
+ product.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> * right.<#= GetRegisterFieldName(type, g) #>);
<#
- }
+ }
#>
}
<#
@@ -766,18 +810,19 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=type.Name#>)(object)factor);
+ product.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=typeAliases[type]#>)(object)factor);
<#
- }
+ }
#>
}
<#
@@ -806,18 +851,19 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=type.Name#>)(object)factor);
+ product.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=typeAliases[type]#>)(object)factor);
<#
- }
+ }
#>
}
<#
@@ -841,20 +887,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -864,18 +911,19 @@ namespace System.Numerics
else
{
Vector<T> quotient = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- quotient.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> / right.<#= GetRegisterFieldName(type, g) #>);
+ quotient.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> / right.<#= GetRegisterFieldName(type, g) #>);
<#
- }
+ }
#>
}
<#
@@ -912,18 +960,18 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] & rightBase[g];
}
}
else
{
- result.<#=GetRegisterFieldName(typeof(Int64), 0)#> = left.<#=GetRegisterFieldName(typeof(Int64), 0)#> & right.<#=GetRegisterFieldName(typeof(Int64), 0)#>;
- result.<#=GetRegisterFieldName(typeof(Int64), 1)#> = left.<#=GetRegisterFieldName(typeof(Int64), 1)#> & right.<#=GetRegisterFieldName(typeof(Int64), 1)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 0)#> = left.<#=GetRegisterFieldName(typeof(long), 0)#> & right.<#=GetRegisterFieldName(typeof(long), 0)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 1)#> = left.<#=GetRegisterFieldName(typeof(long), 1)#> & right.<#=GetRegisterFieldName(typeof(long), 1)#>;
}
}
return result;
@@ -943,18 +991,18 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] | rightBase[g];
}
}
else
{
- result.<#=GetRegisterFieldName(typeof(Int64), 0)#> = left.<#=GetRegisterFieldName(typeof(Int64), 0)#> | right.<#=GetRegisterFieldName(typeof(Int64), 0)#>;
- result.<#=GetRegisterFieldName(typeof(Int64), 1)#> = left.<#=GetRegisterFieldName(typeof(Int64), 1)#> | right.<#=GetRegisterFieldName(typeof(Int64), 1)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 0)#> = left.<#=GetRegisterFieldName(typeof(long), 0)#> | right.<#=GetRegisterFieldName(typeof(long), 0)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 1)#> = left.<#=GetRegisterFieldName(typeof(long), 1)#> | right.<#=GetRegisterFieldName(typeof(long), 1)#>;
}
}
return result;
@@ -974,18 +1022,18 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] ^ rightBase[g];
}
}
else
{
- result.<#=GetRegisterFieldName(typeof(Int64), 0)#> = left.<#=GetRegisterFieldName(typeof(Int64), 0)#> ^ right.<#=GetRegisterFieldName(typeof(Int64), 0)#>;
- result.<#=GetRegisterFieldName(typeof(Int64), 1)#> = left.<#=GetRegisterFieldName(typeof(Int64), 1)#> ^ right.<#=GetRegisterFieldName(typeof(Int64), 1)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 0)#> = left.<#=GetRegisterFieldName(typeof(long), 0)#> ^ right.<#=GetRegisterFieldName(typeof(long), 0)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 1)#> = left.<#=GetRegisterFieldName(typeof(long), 1)#> ^ right.<#=GetRegisterFieldName(typeof(long), 1)#>;
}
}
return result;
@@ -1030,7 +1078,8 @@ namespace System.Numerics
#endregion Logical Operators
#region Conversions
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
/// <summary>
@@ -1047,9 +1096,9 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static explicit operator Vector<<#=type.Name#>>(Vector<T> value)
+ public static explicit operator Vector<<#=typeAliases[type]#>>(Vector<T> value)
{
- return new Vector<<#=type.Name#>>(ref value.register);
+ return new Vector<<#=typeAliases[type]#>>(ref value.register);
}
<#
@@ -1064,15 +1113,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
}
return new Vector<T>(dataPtr);
}
@@ -1087,23 +1137,24 @@ namespace System.Numerics
else
{
Register register = new Register();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> == right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> == right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
<#
- }
+ }
#>
return new Vector<T>(ref register);
}
<#
- }
+ }
#>
else
{
@@ -1118,15 +1169,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
}
return new Vector<T>(dataPtr);
}
@@ -1141,8 +1193,9 @@ namespace System.Numerics
else
{
Register register = new Register();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
@@ -1150,14 +1203,14 @@ namespace System.Numerics
for (int g = 0; g < GetNumFields(type, totalSize); g++)
{
#>
- <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> < right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> < right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
<#
}
#>
return new Vector<T>(ref register);
}
<#
- }
+ }
#>
else
{
@@ -1172,15 +1225,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
}
return new Vector<T>(dataPtr);
}
@@ -1195,23 +1249,24 @@ namespace System.Numerics
else
{
Register register = new Register();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> > right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> > right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
<#
- }
+ }
#>
return new Vector<T>(ref register);
}
<#
- }
+ }
#>
else
{
@@ -1265,10 +1320,10 @@ namespace System.Numerics
#>
<#=GenerateIfStatementHeader(type, supportedTypes.Except(unsignedTypes))#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)(Math.Abs((<#=type.Name#>)(object)value[g]));
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)(Math.Abs((<#=typeAliases[type]#>)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
@@ -1292,7 +1347,7 @@ namespace System.Numerics
for (int g = 0; g < GetNumFields(type, totalSize); g++)
{
#>
- value.<#=GetRegisterFieldName(type, g)#> = (<#=type.Name#>)(Math.Abs(value.<#=GetRegisterFieldName(type, g)#>));
+ value.<#=GetRegisterFieldName(type, g)#> = (<#=typeAliases[type]#>)(Math.Abs(value.<#=GetRegisterFieldName(type, g)#>));
<#
}
#>
@@ -1313,15 +1368,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (<#=type.Name#>)(object)left[g] : (<#=type.Name#>)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (<#=typeAliases[type]#>)(object)left[g] : (<#=typeAliases[type]#>)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -1336,23 +1392,24 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
vec.<#=GetRegisterFieldName(type, g)#> = left.<#=GetRegisterFieldName(type, g)#> < right.<#=GetRegisterFieldName(type, g)#> ? left.<#=GetRegisterFieldName(type, g)#> : right.<#=GetRegisterFieldName(type, g)#>;
<#
- }
+ }
#>
return vec;
}
<#
- }
+ }
#>
else
{
@@ -1366,15 +1423,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (<#=type.Name#>)(object)left[g] : (<#=type.Name#>)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (<#=typeAliases[type]#>)(object)left[g] : (<#=typeAliases[type]#>)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -1389,23 +1447,24 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
vec.<#=GetRegisterFieldName(type, g)#> = left.<#=GetRegisterFieldName(type, g)#> > right.<#=GetRegisterFieldName(type, g)#> ? left.<#=GetRegisterFieldName(type, g)#> : right.<#=GetRegisterFieldName(type, g)#>;
<#
- }
+ }
#>
return vec;
}
<#
- }
+ }
#>
else
{
@@ -1428,24 +1487,25 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
- {
- #>
+<#
+ foreach (Type type in supportedTypes)
+ {
+#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#> product = 0;
+ <#=typeAliases[type]#> product = 0;
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product += (<#=type.Name#>)(left.<#=GetRegisterFieldName(type, g)#> * right.<#=GetRegisterFieldName(type, g)#>);
+ product += (<#=typeAliases[type]#>)(left.<#=GetRegisterFieldName(type, g)#> * right.<#=GetRegisterFieldName(type, g)#>);
<#
- }
+ }
#>
return (T)(object)product;
}
<#
- }
+ }
#>
else
{
@@ -1459,20 +1519,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((<#=type.Name#>)Math.Sqrt((<#=type.Name#>)(object)value[g]));
+ dataPtr[g] = unchecked((<#=typeAliases[type]#>)Math.Sqrt((<#=typeAliases[type]#>)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -1481,23 +1542,24 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- value.<#=GetRegisterFieldName(type, g)#> = (<#=type.Name#>)Math.Sqrt(value.<#=GetRegisterFieldName(type, g)#>);
+ value.<#=GetRegisterFieldName(type, g)#> = (<#=typeAliases[type]#>)Math.Sqrt(value.<#=GetRegisterFieldName(type, g)#>);
<#
- }
+ }
#>
return value;
}
<#
- }
+ }
#>
else
{
@@ -1511,15 +1573,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarEquals(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (<#=type.Name#>)(object)left == (<#=type.Name#>)(object)right;
+ return (<#=typeAliases[type]#>)(object)left == (<#=typeAliases[type]#>)(object)right;
}
<#
- }
+ }
#>
else
{
@@ -1530,15 +1593,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarLessThan(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (<#=type.Name#>)(object)left < (<#=type.Name#>)(object)right;
+ return (<#=typeAliases[type]#>)(object)left < (<#=typeAliases[type]#>)(object)right;
}
<#
- }
+ }
#>
else
{
@@ -1549,15 +1613,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarGreaterThan(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (<#=type.Name#>)(object)left > (<#=type.Name#>)(object)right;
+ return (<#=typeAliases[type]#>)(object)left > (<#=typeAliases[type]#>)(object)right;
}
<#
- }
+ }
#>
else
{
@@ -1568,15 +1633,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarAdd(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)unchecked((<#=type.Name#>)((<#=type.Name#>)(object)left + (<#=type.Name#>)(object)right));
+ return (T)(object)unchecked((<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left + (<#=typeAliases[type]#>)(object)right));
}
<#
- }
+ }
#>
else
{
@@ -1587,15 +1653,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarSubtract(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)(<#=type.Name#>)((<#=type.Name#>)(object)left - (<#=type.Name#>)(object)right);
+ return (T)(object)(<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left - (<#=typeAliases[type]#>)(object)right);
}
<#
- }
+ }
#>
else
{
@@ -1606,15 +1673,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarMultiply(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)unchecked((<#=type.Name#>)((<#=type.Name#>)(object)left * (<#=type.Name#>)(object)right));
+ return (T)(object)unchecked((<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left * (<#=typeAliases[type]#>)(object)right));
}
<#
- }
+ }
#>
else
{
@@ -1625,15 +1693,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarDivide(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)(<#=type.Name#>)((<#=type.Name#>)(object)left / (<#=type.Name#>)(object)right);
+ return (T)(object)(<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left / (<#=typeAliases[type]#>)(object)right);
}
<#
- }
+ }
#>
else
{
@@ -1644,16 +1713,17 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetOneValue()
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#> value = 1;
+ <#=typeAliases[type]#> value = 1;
return (T)(object)value;
}
<#
- }
+ }
#>
else
{
@@ -1664,15 +1734,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetAllBitsSetValue()
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
return (T)(object)ConstantHelper.Get<#=type.Name#>WithAllBitsSet();
}
<#
- }
+ }
#>
else
{
@@ -1686,7 +1757,8 @@ namespace System.Numerics
public static partial class Vector
{
#region Widen/Narrow
-<# foreach (Type type in WidenableTypes)
+<#
+ foreach (Type type in WidenableTypes)
{
Type widenTarget = GetWidenTarget(type);
#>
@@ -1705,28 +1777,28 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static unsafe void Widen(Vector<<#=type.Name#>> source, out Vector<<#=widenTarget.Name#>> low, out Vector<<#=widenTarget.Name#>> high)
+ public static unsafe void Widen(Vector<<#=typeAliases[type]#>> source, out Vector<<#=typeAliases[widenTarget]#>> low, out Vector<<#=typeAliases[widenTarget]#>> high)
{
- int elements = Vector<<#=type.Name#>>.Count;
- <#=widenTarget.Name#>* lowPtr = stackalloc <#=widenTarget.Name#>[elements / 2];
+ int elements = Vector<<#=typeAliases[type]#>>.Count;
+ <#=typeAliases[widenTarget]#>* lowPtr = stackalloc <#=typeAliases[widenTarget]#>[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (<#=widenTarget.Name#>)source[i];
+ lowPtr[i] = (<#=typeAliases[widenTarget]#>)source[i];
}
- <#=widenTarget.Name#>* highPtr = stackalloc <#=widenTarget.Name#>[elements / 2];
+ <#=typeAliases[widenTarget]#>* highPtr = stackalloc <#=typeAliases[widenTarget]#>[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (<#=widenTarget.Name#>)source[i + (elements / 2)];
+ highPtr[i] = (<#=typeAliases[widenTarget]#>)source[i + (elements / 2)];
}
- low = new Vector<<#=widenTarget.Name#>>(lowPtr);
- high = new Vector<<#=widenTarget.Name#>>(highPtr);
+ low = new Vector<<#=typeAliases[widenTarget]#>>(lowPtr);
+ high = new Vector<<#=typeAliases[widenTarget]#>>(highPtr);
}
<#
}
-#>
-<# foreach (Type narrowSource in NarrowableTypes)
+
+ foreach (Type narrowSource in NarrowableTypes)
{
Type narrowTarget = GetNarrowTarget(narrowSource);
#>
@@ -1745,23 +1817,23 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static unsafe Vector<<#=narrowTarget.Name#>> Narrow(Vector<<#=narrowSource.Name#>> low, Vector<<#=narrowSource.Name#>> high)
+ public static unsafe Vector<<#=typeAliases[narrowTarget]#>> Narrow(Vector<<#=typeAliases[narrowSource]#>> low, Vector<<#=typeAliases[narrowSource]#>> high)
{
- unchecked
- {
- int elements = Vector<<#=narrowTarget.Name#>>.Count;
- <#=narrowTarget.Name#>* retPtr = stackalloc <#=narrowTarget.Name#>[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (<#=narrowTarget.Name#>)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (<#=narrowTarget.Name#>)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<<#=typeAliases[narrowTarget]#>>.Count;
+ <#=typeAliases[narrowTarget]#>* retPtr = stackalloc <#=typeAliases[narrowTarget]#>[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (<#=typeAliases[narrowTarget]#>)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (<#=typeAliases[narrowTarget]#>)high[i];
+ }
- return new Vector<<#=narrowTarget.Name#>>(retPtr);
- }
+ return new Vector<<#=typeAliases[narrowTarget]#>>(retPtr);
+ }
}
<#
@@ -1770,7 +1842,8 @@ namespace System.Numerics
#endregion Widen/Narrow
#region Same-Size Conversion
-<# foreach (var pair in SameSizeConversionPairs)
+<#
+ foreach (var pair in SameSizeConversionPairs)
{
#>
/// <summary>
@@ -1787,22 +1860,24 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static unsafe Vector<<#=pair.Value.Name#>> ConvertTo<#=pair.Value.Name#>(Vector<<#=pair.Key.Name#>> value)
+ public static unsafe Vector<<#=typeAliases[pair.Value]#>> ConvertTo<#=pair.Value.Name#>(Vector<<#=typeAliases[pair.Key]#>> value)
{
- unchecked
- {
- int elements = Vector<<#=pair.Value.Name#>>.Count;
- <#=pair.Value.Name#>* retPtr = stackalloc <#=pair.Value.Name#>[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (<#=pair.Value.Name#>)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<<#=typeAliases[pair.Value]#>>.Count;
+ <#=typeAliases[pair.Value]#>* retPtr = stackalloc <#=typeAliases[pair.Value]#>[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (<#=typeAliases[pair.Value]#>)value[i];
+ }
- return new Vector<<#=pair.Value.Name#>>(retPtr);
- }
+ return new Vector<<#=typeAliases[pair.Value]#>>(retPtr);
+ }
}
-<# } #>
+<#
+ }
+#>
#endregion Same-Size Conversion
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs b/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs
index b69b058be..d3ed2509d 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs
@@ -22,9 +22,9 @@ namespace System.Numerics
/// <param name="right">The second source vector.</param>
/// <returns>The new vector with elements selected based on the mask.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Single> ConditionalSelect(Vector<int> condition, Vector<Single> left, Vector<Single> right)
+ public static Vector<float> ConditionalSelect(Vector<int> condition, Vector<float> left, Vector<float> right)
{
- return (Vector<Single>)Vector<Single>.ConditionalSelect((Vector<Single>)condition, left, right);
+ return (Vector<float>)Vector<float>.ConditionalSelect((Vector<float>)condition, left, right);
}
/// <summary>
@@ -75,9 +75,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> Equals(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> Equals(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.Equals(left, right);
+ return (Vector<int>)Vector<float>.Equals(left, right);
}
/// <summary>
@@ -163,9 +163,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> LessThan(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> LessThan(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.LessThan(left, right);
+ return (Vector<int>)Vector<float>.LessThan(left, right);
}
/// <summary>
@@ -256,9 +256,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> LessThanOrEqual(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> LessThanOrEqual(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.LessThanOrEqual(left, right);
+ return (Vector<int>)Vector<float>.LessThanOrEqual(left, right);
}
/// <summary>
@@ -349,9 +349,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> GreaterThan(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> GreaterThan(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.GreaterThan(left, right);
+ return (Vector<int>)Vector<float>.GreaterThan(left, right);
}
/// <summary>
@@ -443,9 +443,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> GreaterThanOrEqual(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> GreaterThanOrEqual(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.GreaterThanOrEqual(left, right);
+ return (Vector<int>)Vector<float>.GreaterThanOrEqual(left, right);
}
/// <summary>
@@ -752,9 +752,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Byte> AsVectorByte<T>(Vector<T> value) where T : struct
+ public static Vector<byte> AsVectorByte<T>(Vector<T> value) where T : struct
{
- return (Vector<Byte>)value;
+ return (Vector<byte>)value;
}
/// <summary>
@@ -764,9 +764,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<SByte> AsVectorSByte<T>(Vector<T> value) where T : struct
+ public static Vector<sbyte> AsVectorSByte<T>(Vector<T> value) where T : struct
{
- return (Vector<SByte>)value;
+ return (Vector<sbyte>)value;
}
/// <summary>
@@ -776,9 +776,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<UInt16> AsVectorUInt16<T>(Vector<T> value) where T : struct
+ public static Vector<ushort> AsVectorUInt16<T>(Vector<T> value) where T : struct
{
- return (Vector<UInt16>)value;
+ return (Vector<ushort>)value;
}
/// <summary>
@@ -787,9 +787,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Int16> AsVectorInt16<T>(Vector<T> value) where T : struct
+ public static Vector<short> AsVectorInt16<T>(Vector<T> value) where T : struct
{
- return (Vector<Int16>)value;
+ return (Vector<short>)value;
}
/// <summary>
@@ -799,9 +799,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<UInt32> AsVectorUInt32<T>(Vector<T> value) where T : struct
+ public static Vector<uint> AsVectorUInt32<T>(Vector<T> value) where T : struct
{
- return (Vector<UInt32>)value;
+ return (Vector<uint>)value;
}
/// <summary>
@@ -810,9 +810,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Int32> AsVectorInt32<T>(Vector<T> value) where T : struct
+ public static Vector<int> AsVectorInt32<T>(Vector<T> value) where T : struct
{
- return (Vector<Int32>)value;
+ return (Vector<int>)value;
}
/// <summary>
@@ -822,9 +822,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<UInt64> AsVectorUInt64<T>(Vector<T> value) where T : struct
+ public static Vector<ulong> AsVectorUInt64<T>(Vector<T> value) where T : struct
{
- return (Vector<UInt64>)value;
+ return (Vector<ulong>)value;
}
@@ -834,9 +834,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Int64> AsVectorInt64<T>(Vector<T> value) where T : struct
+ public static Vector<long> AsVectorInt64<T>(Vector<T> value) where T : struct
{
- return (Vector<Int64>)value;
+ return (Vector<long>)value;
}
/// <summary>
@@ -845,9 +845,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Single> AsVectorSingle<T>(Vector<T> value) where T : struct
+ public static Vector<float> AsVectorSingle<T>(Vector<T> value) where T : struct
{
- return (Vector<Single>)value;
+ return (Vector<float>)value;
}
/// <summary>
@@ -856,9 +856,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Double> AsVectorDouble<T>(Vector<T> value) where T : struct
+ public static Vector<double> AsVectorDouble<T>(Vector<T> value) where T : struct
{
- return (Vector<Double>)value;
+ return (Vector<double>)value;
}
#endregion Conversion Methods
}
diff --git a/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs b/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs
index 3daed13bb..8f13055b9 100644
--- a/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs
+++ b/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs
@@ -15,7 +15,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ObjectDisposedException : InvalidOperationException
{
- private String _objectName;
+ private string _objectName;
// This constructor should only be called by the EE (COMPlusThrow)
private ObjectDisposedException() :
@@ -23,18 +23,18 @@ namespace System
{
}
- public ObjectDisposedException(String objectName) :
+ public ObjectDisposedException(string objectName) :
this(objectName, SR.ObjectDisposed_Generic)
{
}
- public ObjectDisposedException(String objectName, String message) : base(message)
+ public ObjectDisposedException(string objectName, string message) : base(message)
{
HResult = HResults.COR_E_OBJECTDISPOSED;
_objectName = objectName;
}
- public ObjectDisposedException(String message, Exception innerException)
+ public ObjectDisposedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OBJECTDISPOSED;
@@ -55,26 +55,26 @@ namespace System
/// <devdoc>
/// <para>Gets the text for the message for this exception.</para>
/// </devdoc>
- public override String Message
+ public override string Message
{
get
{
- String name = ObjectName;
+ string name = ObjectName;
if (name == null || name.Length == 0)
return base.Message;
- String objectDisposed = SR.Format(SR.ObjectDisposed_ObjectName_Name, name);
+ string objectDisposed = SR.Format(SR.ObjectDisposed_ObjectName_Name, name);
return base.Message + Environment.NewLine + objectDisposed;
}
}
- public String ObjectName
+ public string ObjectName
{
get
{
if (_objectName == null)
{
- return String.Empty;
+ return string.Empty;
}
return _objectName;
}
diff --git a/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs b/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs
index a63db137f..748681756 100644
--- a/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs
@@ -26,7 +26,7 @@ namespace System
, Inherited = false)]
public sealed class ObsoleteAttribute : Attribute
{
- private String _message;
+ private string _message;
private bool _error;
public ObsoleteAttribute()
@@ -35,19 +35,19 @@ namespace System
_error = false;
}
- public ObsoleteAttribute(String message)
+ public ObsoleteAttribute(string message)
{
_message = message;
_error = false;
}
- public ObsoleteAttribute(String message, bool error)
+ public ObsoleteAttribute(string message, bool error)
{
_message = message;
_error = error;
}
- public String Message
+ public string Message
{
get { return _message; }
}
diff --git a/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs b/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs
index 8a472c9ff..0c311afd7 100644
--- a/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs
+++ b/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs
@@ -36,13 +36,13 @@ namespace System
HResult = HResults.COR_E_OPERATIONCANCELED;
}
- public OperationCanceledException(String message)
+ public OperationCanceledException(string message)
: base(message)
{
HResult = HResults.COR_E_OPERATIONCANCELED;
}
- public OperationCanceledException(String message, Exception innerException)
+ public OperationCanceledException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OPERATIONCANCELED;
@@ -55,13 +55,13 @@ namespace System
CancellationToken = token;
}
- public OperationCanceledException(String message, CancellationToken token)
+ public OperationCanceledException(string message, CancellationToken token)
: this(message)
{
CancellationToken = token;
}
- public OperationCanceledException(String message, Exception innerException, CancellationToken token)
+ public OperationCanceledException(string message, Exception innerException, CancellationToken token)
: this(message, innerException)
{
CancellationToken = token;
diff --git a/src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs b/src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs
new file mode 100644
index 000000000..c59852f78
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs
@@ -0,0 +1,45 @@
+// 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.Runtime.Serialization;
+
+namespace System
+{
+ /// <summary>
+ /// The exception class for OOM.
+ /// </summary>
+ [Serializable]
+#if !MONO
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public class OutOfMemoryException : SystemException
+ {
+ public OutOfMemoryException() : base(
+#if CORECLR
+ GetMessageFromNativeResources(ExceptionMessageKind.OutOfMemory)
+#else
+ SR.Arg_OutOfMemoryException
+#endif
+ )
+ {
+ HResult = HResults.COR_E_OUTOFMEMORY;
+ }
+
+ public OutOfMemoryException(string message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_OUTOFMEMORY;
+ }
+
+ public OutOfMemoryException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ HResult = HResults.COR_E_OUTOFMEMORY;
+ }
+
+ protected OutOfMemoryException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/OverflowException.cs b/src/System.Private.CoreLib/shared/System/OverflowException.cs
index e28dcb87e..c18fe3f7b 100644
--- a/src/System.Private.CoreLib/shared/System/OverflowException.cs
+++ b/src/System.Private.CoreLib/shared/System/OverflowException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_OVERFLOW;
}
- public OverflowException(String message)
+ public OverflowException(string message)
: base(message)
{
HResult = HResults.COR_E_OVERFLOW;
}
- public OverflowException(String message, Exception innerException)
+ public OverflowException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OVERFLOW;
diff --git a/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs b/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs
index 5039f3f44..f9e461ed0 100644
--- a/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs
+++ b/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
- public PlatformNotSupportedException(String message)
+ public PlatformNotSupportedException(string message)
: base(message)
{
HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
- public PlatformNotSupportedException(String message, Exception inner)
+ public PlatformNotSupportedException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
diff --git a/src/System.Private.CoreLib/shared/System/Random.cs b/src/System.Private.CoreLib/shared/System/Random.cs
index 20f035e2e..ed79732c2 100644
--- a/src/System.Private.CoreLib/shared/System/Random.cs
+++ b/src/System.Private.CoreLib/shared/System/Random.cs
@@ -156,7 +156,7 @@ namespace System
/*=====================================Next=====================================
- **Returns: An int [0..Int32.MaxValue)
+ **Returns: An int [0..int.MaxValue)
**Arguments: None
**Exceptions: None.
==============================================================================*/
@@ -169,7 +169,7 @@ namespace System
{
// The distribution of double value returned by Sample
// is not distributed well enough for a large range.
- // If we use Sample for a range [Int32.MinValue..Int32.MaxValue)
+ // If we use Sample for a range [int.MinValue..int.MaxValue)
// We will end up getting even numbers only.
int result = InternalSample();
diff --git a/src/System.Private.CoreLib/shared/System/RankException.cs b/src/System.Private.CoreLib/shared/System/RankException.cs
index bdd2cd51f..e1e7d169b 100644
--- a/src/System.Private.CoreLib/shared/System/RankException.cs
+++ b/src/System.Private.CoreLib/shared/System/RankException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_RANK;
}
- public RankException(String message)
+ public RankException(string message)
: base(message)
{
HResult = HResults.COR_E_RANK;
}
- public RankException(String message, Exception innerException)
+ public RankException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_RANK;
diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs b/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
index 166a204ed..02445ec5c 100644
--- a/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
+++ b/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
@@ -8,9 +8,8 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
-#if !FEATURE_PORTABLE_SPAN
+
using Internal.Runtime.CompilerServices;
-#endif // FEATURE_PORTABLE_SPAN
namespace System
{
@@ -18,21 +17,23 @@ namespace System
/// Represents a contiguous region of memory, similar to <see cref="ReadOnlySpan{T}"/>.
/// Unlike <see cref="ReadOnlySpan{T}"/>, it is not a byref-like type.
/// </summary>
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
+ [DebuggerDisplay("{ToString(),raw}")]
public readonly struct ReadOnlyMemory<T>
{
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
// as code uses Unsafe.As to cast between them.
// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
- // if (_index >> 31) == 1, _object is an OwnedMemory<T>
- // else, _object is a T[] or string
+ // if (_index >> 31) == 1, _object is an MemoryManager<T>
+ // else, _object is a T[] or string.
+ // if (_length >> 31) == 1, _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
+ // else, Pin() needs to allocate a new GCHandle to pin the object.
private readonly object _object;
private readonly int _index;
private readonly int _length;
- internal const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+ internal const int RemoveFlagsBitMask = 0x7FFFFFFF;
/// <summary>
/// Creates a new memory over the entirety of the target array.
@@ -97,9 +98,6 @@ namespace System
_length = length;
}
- //Debugger Display = {T[length]}
- private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
-
/// <summary>
/// Defines an implicit conversion of an array to a <see cref="ReadOnlyMemory{T}"/>
/// </summary>
@@ -108,7 +106,7 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlyMemory{T}"/>
/// </summary>
- public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> arraySegment) => new ReadOnlyMemory<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> segment) => new ReadOnlyMemory<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Returns an empty <see cref="ReadOnlyMemory{T}"/>
@@ -118,12 +116,25 @@ namespace System
/// <summary>
/// The number of items in the memory.
/// </summary>
- public int Length => _length;
+ public int Length => _length & RemoveFlagsBitMask;
/// <summary>
/// Returns true if Length is 0.
/// </summary>
- public bool IsEmpty => _length == 0;
+ public bool IsEmpty => (_length & RemoveFlagsBitMask) == 0;
+
+ /// <summary>
+ /// For <see cref="ReadOnlyMemory{Char}"/>, returns a new instance of string that represents the characters pointed to by the memory.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+ /// </summary>
+ public override string ToString()
+ {
+ if (typeof(T) == typeof(char))
+ {
+ return (_object is string str) ? str.Substring(_index, _length & RemoveFlagsBitMask) : Span.ToString();
+ }
+ return string.Format("System.ReadOnlyMemory<{0}>[{1}]", typeof(T).Name, _length & RemoveFlagsBitMask);
+ }
/// <summary>
/// Forms a slice out of the given memory, beginning at 'start'.
@@ -135,12 +146,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyMemory<T> Slice(int start)
{
- if ((uint)start > (uint)_length)
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = capturedLength & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
}
- return new ReadOnlyMemory<T>(_object, _index + start, _length - start);
+ // It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned.
+ return new ReadOnlyMemory<T>(_object, _index + start, capturedLength - start);
}
/// <summary>
@@ -154,12 +169,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyMemory<T> Slice(int start, int length)
{
- if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = _length & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start))
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
}
- return new ReadOnlyMemory<T>(_object, _index + start, length);
+ // Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned).
+ return new ReadOnlyMemory<T>(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask));
}
/// <summary>
@@ -172,19 +191,18 @@ namespace System
{
if (_index < 0)
{
- return ((OwnedMemory<T>)_object).Span.Slice(_index & RemoveOwnedFlagBitMask, _length);
+ Debug.Assert(_length >= 0);
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).GetSpan().Slice(_index & RemoveFlagsBitMask, _length);
}
else if (typeof(T) == typeof(char) && _object is string s)
{
-#if FEATURE_PORTABLE_SPAN
- return new ReadOnlySpan<T>(Unsafe.As<Pinnable<T>>(s), MemoryExtensions.StringAdjustment, s.Length).Slice(_index, _length);
-#else
+ Debug.Assert(_length >= 0);
return new ReadOnlySpan<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
-#endif // FEATURE_PORTABLE_SPAN
}
else if (_object != null)
{
- return new ReadOnlySpan<T>((T[])_object, _index, _length);
+ return new ReadOnlySpan<T>((T[])_object, _index, _length & RemoveFlagsBitMask);
}
else
{
@@ -216,50 +234,43 @@ namespace System
/// <param name="destination">The span to copy items into.</param>
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span);
- /// <summary>Creates a handle for the memory.</summary>
- /// <param name="pin">
- /// If pin is true, the GC will not move the array until the returned <see cref="MemoryHandle"/>
- /// is disposed, enabling the memory's address can be taken and used.
- /// </param>
- public unsafe MemoryHandle Retain(bool pin = false)
+ /// <summary>
+ /// Creates a handle for the memory.
+ /// The GC will not move the memory until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
+ /// <exception cref="System.ArgumentException">
+ /// An instance with nonprimitive (non-blittable) members cannot be pinned.
+ /// </exception>
+ /// </summary>
+ public unsafe MemoryHandle Pin()
{
- MemoryHandle memoryHandle = default;
- if (pin)
+ if (_index < 0)
{
- if (_index < 0)
- {
- memoryHandle = ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>());
- }
- else if (typeof(T) == typeof(char) && _object is string s)
- {
- GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
- void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
- }
- else if (_object is T[] array)
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).Pin((_index & RemoveFlagsBitMask));
+ }
+ else if (typeof(T) == typeof(char) && _object is string s)
+ {
+ GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
+ return new MemoryHandle(pointer, handle);
+ }
+ else if (_object is T[] array)
+ {
+ // Array is already pre-pinned
+ if (_length < 0)
{
- var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
+ return new MemoryHandle(pointer);
}
- }
- else
- {
- if (_index < 0)
+ else
{
- ((OwnedMemory<T>)_object).Retain();
- memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+ return new MemoryHandle(pointer, handle);
}
}
- return memoryHandle;
+ return default;
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs
index 9bf3f211a..4fb039a0f 100644
--- a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs
@@ -2,10 +2,11 @@
// 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.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
+using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
using Internal.Runtime.CompilerServices;
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -22,8 +23,6 @@ namespace System
/// ReadOnlySpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
- [DebuggerTypeProxy(typeof(SpanDebugView<>))]
- [DebuggerDisplay("{ToString(),raw}")]
[NonVersionable]
public readonly ref partial struct ReadOnlySpan<T>
{
@@ -150,6 +149,13 @@ namespace System
}
/// <summary>
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
+ /// It can be used for pinning and is required to support the use of span within a fixed statement.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe ref readonly T GetPinnableReference() => ref (_length != 0) ? ref _pointer.Value : ref Unsafe.AsRef<T>(null);
+
+ /// <summary>
/// Copies the contents of this read-only span into destination span. If the source
/// and destinations overlap, this method behaves as if the original values in
/// a temporary location before the destination is overwritten.
@@ -159,6 +165,7 @@ namespace System
/// Thrown when the destination Span is shorter than the source Span.
/// </exception>
/// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Span<T> destination)
{
// Using "if (!TryCopyTo(...))" results in two branches: one for the length
@@ -204,7 +211,7 @@ namespace System
/// <summary>
/// For <see cref="ReadOnlySpan{Char}"/>, returns a new instance of string that represents the characters pointed to by the span.
- /// Otherwise, returns a <see cref="String"/> with the name of the type and the number of elements.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
/// </summary>
public override string ToString()
{
diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs
index 906a3c431..17b7134e2 100644
--- a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs
+++ b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs
@@ -5,9 +5,8 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
-#if !FEATURE_PORTABLE_SPAN
+
using System.Runtime.Versioning;
-#endif // !FEATURE_PORTABLE_SPAN
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -26,9 +25,7 @@ namespace System
/// </summary>
public int Length
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
return _length;
@@ -40,12 +37,11 @@ namespace System
/// </summary>
public bool IsEmpty
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
- return _length == 0;
+ // Workaround for https://github.com/dotnet/coreclr/issues/19620
+ return 0 >= (uint)_length;
}
}
/// <summary>
@@ -88,13 +84,13 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlySpan{T}"/>
/// </summary>
- public static implicit operator ReadOnlySpan<T>(ArraySegment<T> arraySegment)
- => new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment)
+ => new ReadOnlySpan<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Returns a 0-length read-only span whose base is the null pointer.
/// </summary>
- public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>);
+ public static ReadOnlySpan<T> Empty => default;
/// <summary>Gets an enumerator for this span.</summary>
public Enumerator GetEnumerator() => new Enumerator(this);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
index 7280869c0..f22c8c40e 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
@@ -141,7 +141,7 @@ namespace System.Reflection
Returns true if the assembly was loaded from the global assembly cache.
*/
public virtual bool GlobalAssemblyCache { get { throw NotImplemented.ByDesign; } }
- public virtual Int64 HostContext { get { throw NotImplemented.ByDesign; } }
+ public virtual long HostContext { get { throw NotImplemented.ByDesign; } }
public override bool Equals(object o) => base.Equals(o);
public override int GetHashCode() => base.GetHashCode();
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs
index 716afb045..90ccd1fe5 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs
@@ -111,8 +111,7 @@ namespace System.Reflection
continue;
if ((s.Length - i) < escapeReplacement.Length)
continue;
- string prefix = s.Substring(i, escapeReplacement.Length);
- if (prefix == escapeReplacement)
+ if (s.AsSpan(i, escapeReplacement.Length).SequenceEqual(escapeReplacement))
{
sb.Append('\\');
sb.Append(kv.Key);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs
new file mode 100644
index 000000000..b09696040
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs
@@ -0,0 +1,18 @@
+// 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;
+
+// This enumeration defines the access modes for a dynamic assembly.
+// EE uses these enum values..look for m_dwDynamicAssemblyAccess in Assembly.hpp
+
+namespace System.Reflection.Emit
+{
+ [Flags]
+ public enum AssemblyBuilderAccess
+ {
+ Run = 1,
+ RunAndCollect = 8 | Run
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs
new file mode 100644
index 000000000..8905a7f1d
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs
@@ -0,0 +1,32 @@
+// 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.
+
+/*============================================================
+**
+** Enumeration: FlowControl
+**
+** Purpose: Exposes FlowControl Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum FlowControl
+ {
+ Branch = 0,
+ Break = 1,
+ Call = 2,
+ Cond_Branch = 3,
+ Meta = 4,
+ Next = 5,
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ Phi = 6,
+ Return = 7,
+ Throw = 8,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs
new file mode 100644
index 000000000..e49d471a9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs
@@ -0,0 +1,75 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Represents a Label to the ILGenerator class.
+**
+**
+===========================================================*/
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace System.Reflection.Emit
+{
+ // The Label class is an opaque representation of a label used by the
+ // ILGenerator class. The token is used to mark where labels occur in the IL
+ // stream and then the necessary offsets are put back in the code when the ILGenerator
+ // is passed to the MethodWriter.
+ // Labels are created by using ILGenerator.CreateLabel and their position is set
+ // by using ILGenerator.MarkLabel.
+ public struct Label
+ {
+ internal int m_label;
+
+ //public Label() {
+ // m_label=0;
+ //}
+
+ internal Label(int label)
+ {
+ m_label = label;
+ }
+
+ internal int GetLabelValue()
+ {
+ return m_label;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_label;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Label)
+ return Equals((Label)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(Label obj)
+ {
+ return obj.m_label == m_label;
+ }
+
+ public static bool operator ==(Label a, Label b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(Label a, Label b)
+ {
+ return !(a == b);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs
new file mode 100644
index 000000000..17435c576
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs
@@ -0,0 +1,29 @@
+// 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.
+
+/*============================================================
+**
+** Enumeration: OpCodeType
+**
+** Purpose: Exposes OpCodeType Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum OpCodeType
+ {
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ Annotation = 0,
+ Macro = 1,
+ Nternal = 2,
+ Objmodel = 3,
+ Prefix = 4,
+ Primitive = 5,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs
new file mode 100644
index 000000000..7690005e2
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs
@@ -0,0 +1,2539 @@
+// 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.
+
+namespace System.Reflection.Emit
+{
+ //
+ // Internal enums for opcode values. Note that the value names are used to construct
+ // publicly visible ilasm-compatible opcode names, so their exact form is important!
+ //
+ internal enum OpCodeValues
+ {
+ Nop = 0x00,
+ Break = 0x01,
+ Ldarg_0 = 0x02,
+ Ldarg_1 = 0x03,
+ Ldarg_2 = 0x04,
+ Ldarg_3 = 0x05,
+ Ldloc_0 = 0x06,
+ Ldloc_1 = 0x07,
+ Ldloc_2 = 0x08,
+ Ldloc_3 = 0x09,
+ Stloc_0 = 0x0a,
+ Stloc_1 = 0x0b,
+ Stloc_2 = 0x0c,
+ Stloc_3 = 0x0d,
+ Ldarg_S = 0x0e,
+ Ldarga_S = 0x0f,
+ Starg_S = 0x10,
+ Ldloc_S = 0x11,
+ Ldloca_S = 0x12,
+ Stloc_S = 0x13,
+ Ldnull = 0x14,
+ Ldc_I4_M1 = 0x15,
+ Ldc_I4_0 = 0x16,
+ Ldc_I4_1 = 0x17,
+ Ldc_I4_2 = 0x18,
+ Ldc_I4_3 = 0x19,
+ Ldc_I4_4 = 0x1a,
+ Ldc_I4_5 = 0x1b,
+ Ldc_I4_6 = 0x1c,
+ Ldc_I4_7 = 0x1d,
+ Ldc_I4_8 = 0x1e,
+ Ldc_I4_S = 0x1f,
+ Ldc_I4 = 0x20,
+ Ldc_I8 = 0x21,
+ Ldc_R4 = 0x22,
+ Ldc_R8 = 0x23,
+ Dup = 0x25,
+ Pop = 0x26,
+ Jmp = 0x27,
+ Call = 0x28,
+ Calli = 0x29,
+ Ret = 0x2a,
+ Br_S = 0x2b,
+ Brfalse_S = 0x2c,
+ Brtrue_S = 0x2d,
+ Beq_S = 0x2e,
+ Bge_S = 0x2f,
+ Bgt_S = 0x30,
+ Ble_S = 0x31,
+ Blt_S = 0x32,
+ Bne_Un_S = 0x33,
+ Bge_Un_S = 0x34,
+ Bgt_Un_S = 0x35,
+ Ble_Un_S = 0x36,
+ Blt_Un_S = 0x37,
+ Br = 0x38,
+ Brfalse = 0x39,
+ Brtrue = 0x3a,
+ Beq = 0x3b,
+ Bge = 0x3c,
+ Bgt = 0x3d,
+ Ble = 0x3e,
+ Blt = 0x3f,
+ Bne_Un = 0x40,
+ Bge_Un = 0x41,
+ Bgt_Un = 0x42,
+ Ble_Un = 0x43,
+ Blt_Un = 0x44,
+ Switch = 0x45,
+ Ldind_I1 = 0x46,
+ Ldind_U1 = 0x47,
+ Ldind_I2 = 0x48,
+ Ldind_U2 = 0x49,
+ Ldind_I4 = 0x4a,
+ Ldind_U4 = 0x4b,
+ Ldind_I8 = 0x4c,
+ Ldind_I = 0x4d,
+ Ldind_R4 = 0x4e,
+ Ldind_R8 = 0x4f,
+ Ldind_Ref = 0x50,
+ Stind_Ref = 0x51,
+ Stind_I1 = 0x52,
+ Stind_I2 = 0x53,
+ Stind_I4 = 0x54,
+ Stind_I8 = 0x55,
+ Stind_R4 = 0x56,
+ Stind_R8 = 0x57,
+ Add = 0x58,
+ Sub = 0x59,
+ Mul = 0x5a,
+ Div = 0x5b,
+ Div_Un = 0x5c,
+ Rem = 0x5d,
+ Rem_Un = 0x5e,
+ And = 0x5f,
+ Or = 0x60,
+ Xor = 0x61,
+ Shl = 0x62,
+ Shr = 0x63,
+ Shr_Un = 0x64,
+ Neg = 0x65,
+ Not = 0x66,
+ Conv_I1 = 0x67,
+ Conv_I2 = 0x68,
+ Conv_I4 = 0x69,
+ Conv_I8 = 0x6a,
+ Conv_R4 = 0x6b,
+ Conv_R8 = 0x6c,
+ Conv_U4 = 0x6d,
+ Conv_U8 = 0x6e,
+ Callvirt = 0x6f,
+ Cpobj = 0x70,
+ Ldobj = 0x71,
+ Ldstr = 0x72,
+ Newobj = 0x73,
+ Castclass = 0x74,
+ Isinst = 0x75,
+ Conv_R_Un = 0x76,
+ Unbox = 0x79,
+ Throw = 0x7a,
+ Ldfld = 0x7b,
+ Ldflda = 0x7c,
+ Stfld = 0x7d,
+ Ldsfld = 0x7e,
+ Ldsflda = 0x7f,
+ Stsfld = 0x80,
+ Stobj = 0x81,
+ Conv_Ovf_I1_Un = 0x82,
+ Conv_Ovf_I2_Un = 0x83,
+ Conv_Ovf_I4_Un = 0x84,
+ Conv_Ovf_I8_Un = 0x85,
+ Conv_Ovf_U1_Un = 0x86,
+ Conv_Ovf_U2_Un = 0x87,
+ Conv_Ovf_U4_Un = 0x88,
+ Conv_Ovf_U8_Un = 0x89,
+ Conv_Ovf_I_Un = 0x8a,
+ Conv_Ovf_U_Un = 0x8b,
+ Box = 0x8c,
+ Newarr = 0x8d,
+ Ldlen = 0x8e,
+ Ldelema = 0x8f,
+ Ldelem_I1 = 0x90,
+ Ldelem_U1 = 0x91,
+ Ldelem_I2 = 0x92,
+ Ldelem_U2 = 0x93,
+ Ldelem_I4 = 0x94,
+ Ldelem_U4 = 0x95,
+ Ldelem_I8 = 0x96,
+ Ldelem_I = 0x97,
+ Ldelem_R4 = 0x98,
+ Ldelem_R8 = 0x99,
+ Ldelem_Ref = 0x9a,
+ Stelem_I = 0x9b,
+ Stelem_I1 = 0x9c,
+ Stelem_I2 = 0x9d,
+ Stelem_I4 = 0x9e,
+ Stelem_I8 = 0x9f,
+ Stelem_R4 = 0xa0,
+ Stelem_R8 = 0xa1,
+ Stelem_Ref = 0xa2,
+ Ldelem = 0xa3,
+ Stelem = 0xa4,
+ Unbox_Any = 0xa5,
+ Conv_Ovf_I1 = 0xb3,
+ Conv_Ovf_U1 = 0xb4,
+ Conv_Ovf_I2 = 0xb5,
+ Conv_Ovf_U2 = 0xb6,
+ Conv_Ovf_I4 = 0xb7,
+ Conv_Ovf_U4 = 0xb8,
+ Conv_Ovf_I8 = 0xb9,
+ Conv_Ovf_U8 = 0xba,
+ Refanyval = 0xc2,
+ Ckfinite = 0xc3,
+ Mkrefany = 0xc6,
+ Ldtoken = 0xd0,
+ Conv_U2 = 0xd1,
+ Conv_U1 = 0xd2,
+ Conv_I = 0xd3,
+ Conv_Ovf_I = 0xd4,
+ Conv_Ovf_U = 0xd5,
+ Add_Ovf = 0xd6,
+ Add_Ovf_Un = 0xd7,
+ Mul_Ovf = 0xd8,
+ Mul_Ovf_Un = 0xd9,
+ Sub_Ovf = 0xda,
+ Sub_Ovf_Un = 0xdb,
+ Endfinally = 0xdc,
+ Leave = 0xdd,
+ Leave_S = 0xde,
+ Stind_I = 0xdf,
+ Conv_U = 0xe0,
+ Prefix7 = 0xf8,
+ Prefix6 = 0xf9,
+ Prefix5 = 0xfa,
+ Prefix4 = 0xfb,
+ Prefix3 = 0xfc,
+ Prefix2 = 0xfd,
+ Prefix1 = 0xfe,
+ Prefixref = 0xff,
+ Arglist = 0xfe00,
+ Ceq = 0xfe01,
+ Cgt = 0xfe02,
+ Cgt_Un = 0xfe03,
+ Clt = 0xfe04,
+ Clt_Un = 0xfe05,
+ Ldftn = 0xfe06,
+ Ldvirtftn = 0xfe07,
+ Ldarg = 0xfe09,
+ Ldarga = 0xfe0a,
+ Starg = 0xfe0b,
+ Ldloc = 0xfe0c,
+ Ldloca = 0xfe0d,
+ Stloc = 0xfe0e,
+ Localloc = 0xfe0f,
+ Endfilter = 0xfe11,
+ Unaligned_ = 0xfe12,
+ Volatile_ = 0xfe13,
+ Tail_ = 0xfe14,
+ Initobj = 0xfe15,
+ Constrained_ = 0xfe16,
+ Cpblk = 0xfe17,
+ Initblk = 0xfe18,
+ Rethrow = 0xfe1a,
+ Sizeof = 0xfe1c,
+ Refanytype = 0xfe1d,
+ Readonly_ = 0xfe1e,
+ // If you add more opcodes here, modify OpCode.Name to handle them correctly
+ }
+
+ /// <summary>
+ /// <para>
+ /// The IL instruction opcodes supported by the
+ /// runtime. The IL Instruction Specification describes each
+ /// Opcode.
+ /// </para>
+ /// </summary>
+ /// <seealso topic='IL Instruction Set Specification'/>
+ public class OpCodes
+ {
+ private OpCodes()
+ {
+ }
+
+ public static readonly OpCode Nop = new OpCode(OpCodeValues.Nop,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Break = new OpCode(OpCodeValues.Break,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Break << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_0 = new OpCode(OpCodeValues.Ldarg_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_1 = new OpCode(OpCodeValues.Ldarg_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_2 = new OpCode(OpCodeValues.Ldarg_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_3 = new OpCode(OpCodeValues.Ldarg_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_0 = new OpCode(OpCodeValues.Ldloc_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_1 = new OpCode(OpCodeValues.Ldloc_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_2 = new OpCode(OpCodeValues.Ldloc_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_3 = new OpCode(OpCodeValues.Ldloc_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_0 = new OpCode(OpCodeValues.Stloc_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_1 = new OpCode(OpCodeValues.Stloc_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_2 = new OpCode(OpCodeValues.Stloc_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_3 = new OpCode(OpCodeValues.Stloc_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_S = new OpCode(OpCodeValues.Ldarg_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarga_S = new OpCode(OpCodeValues.Ldarga_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Starg_S = new OpCode(OpCodeValues.Starg_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_S = new OpCode(OpCodeValues.Ldloc_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloca_S = new OpCode(OpCodeValues.Ldloca_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_S = new OpCode(OpCodeValues.Stloc_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldnull = new OpCode(OpCodeValues.Ldnull,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_M1 = new OpCode(OpCodeValues.Ldc_I4_M1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_0 = new OpCode(OpCodeValues.Ldc_I4_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_1 = new OpCode(OpCodeValues.Ldc_I4_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_2 = new OpCode(OpCodeValues.Ldc_I4_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_3 = new OpCode(OpCodeValues.Ldc_I4_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_4 = new OpCode(OpCodeValues.Ldc_I4_4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_5 = new OpCode(OpCodeValues.Ldc_I4_5,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_6 = new OpCode(OpCodeValues.Ldc_I4_6,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_7 = new OpCode(OpCodeValues.Ldc_I4_7,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_8 = new OpCode(OpCodeValues.Ldc_I4_8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_S = new OpCode(OpCodeValues.Ldc_I4_S,
+ ((int)OperandType.ShortInlineI) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4 = new OpCode(OpCodeValues.Ldc_I4,
+ ((int)OperandType.InlineI) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I8 = new OpCode(OpCodeValues.Ldc_I8,
+ ((int)OperandType.InlineI8) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_R4 = new OpCode(OpCodeValues.Ldc_R4,
+ ((int)OperandType.ShortInlineR) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_R8 = new OpCode(OpCodeValues.Ldc_R8,
+ ((int)OperandType.InlineR) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Dup = new OpCode(OpCodeValues.Dup,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1_push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Pop = new OpCode(OpCodeValues.Pop,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Jmp = new OpCode(OpCodeValues.Jmp,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Call = new OpCode(OpCodeValues.Call,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Calli = new OpCode(OpCodeValues.Calli,
+ ((int)OperandType.InlineSig) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ret = new OpCode(OpCodeValues.Ret,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Br_S = new OpCode(OpCodeValues.Br_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brfalse_S = new OpCode(OpCodeValues.Brfalse_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brtrue_S = new OpCode(OpCodeValues.Brtrue_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Beq_S = new OpCode(OpCodeValues.Beq_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_S = new OpCode(OpCodeValues.Bge_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_S = new OpCode(OpCodeValues.Bgt_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_S = new OpCode(OpCodeValues.Ble_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_S = new OpCode(OpCodeValues.Blt_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bne_Un_S = new OpCode(OpCodeValues.Bne_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_Un_S = new OpCode(OpCodeValues.Bge_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_Un_S = new OpCode(OpCodeValues.Bgt_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_Un_S = new OpCode(OpCodeValues.Ble_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_Un_S = new OpCode(OpCodeValues.Blt_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Br = new OpCode(OpCodeValues.Br,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brfalse = new OpCode(OpCodeValues.Brfalse,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brtrue = new OpCode(OpCodeValues.Brtrue,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Beq = new OpCode(OpCodeValues.Beq,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge = new OpCode(OpCodeValues.Bge,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt = new OpCode(OpCodeValues.Bgt,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble = new OpCode(OpCodeValues.Ble,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt = new OpCode(OpCodeValues.Blt,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bne_Un = new OpCode(OpCodeValues.Bne_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_Un = new OpCode(OpCodeValues.Bge_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_Un = new OpCode(OpCodeValues.Bgt_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_Un = new OpCode(OpCodeValues.Ble_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_Un = new OpCode(OpCodeValues.Blt_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Switch = new OpCode(OpCodeValues.Switch,
+ ((int)OperandType.InlineSwitch) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I1 = new OpCode(OpCodeValues.Ldind_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U1 = new OpCode(OpCodeValues.Ldind_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I2 = new OpCode(OpCodeValues.Ldind_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U2 = new OpCode(OpCodeValues.Ldind_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I4 = new OpCode(OpCodeValues.Ldind_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U4 = new OpCode(OpCodeValues.Ldind_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I8 = new OpCode(OpCodeValues.Ldind_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I = new OpCode(OpCodeValues.Ldind_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_R4 = new OpCode(OpCodeValues.Ldind_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_R8 = new OpCode(OpCodeValues.Ldind_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_Ref = new OpCode(OpCodeValues.Ldind_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_Ref = new OpCode(OpCodeValues.Stind_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I1 = new OpCode(OpCodeValues.Stind_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I2 = new OpCode(OpCodeValues.Stind_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I4 = new OpCode(OpCodeValues.Stind_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I8 = new OpCode(OpCodeValues.Stind_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_R4 = new OpCode(OpCodeValues.Stind_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popr4 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_R8 = new OpCode(OpCodeValues.Stind_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popr8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add = new OpCode(OpCodeValues.Add,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub = new OpCode(OpCodeValues.Sub,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul = new OpCode(OpCodeValues.Mul,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Div = new OpCode(OpCodeValues.Div,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Div_Un = new OpCode(OpCodeValues.Div_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rem = new OpCode(OpCodeValues.Rem,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rem_Un = new OpCode(OpCodeValues.Rem_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode And = new OpCode(OpCodeValues.And,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Or = new OpCode(OpCodeValues.Or,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Xor = new OpCode(OpCodeValues.Xor,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shl = new OpCode(OpCodeValues.Shl,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shr = new OpCode(OpCodeValues.Shr,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shr_Un = new OpCode(OpCodeValues.Shr_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Neg = new OpCode(OpCodeValues.Neg,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Not = new OpCode(OpCodeValues.Not,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I1 = new OpCode(OpCodeValues.Conv_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I2 = new OpCode(OpCodeValues.Conv_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I4 = new OpCode(OpCodeValues.Conv_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I8 = new OpCode(OpCodeValues.Conv_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R4 = new OpCode(OpCodeValues.Conv_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R8 = new OpCode(OpCodeValues.Conv_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U4 = new OpCode(OpCodeValues.Conv_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U8 = new OpCode(OpCodeValues.Conv_U8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Callvirt = new OpCode(OpCodeValues.Callvirt,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cpobj = new OpCode(OpCodeValues.Cpobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldobj = new OpCode(OpCodeValues.Ldobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldstr = new OpCode(OpCodeValues.Ldstr,
+ ((int)OperandType.InlineString) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Newobj = new OpCode(OpCodeValues.Newobj,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Castclass = new OpCode(OpCodeValues.Castclass,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Isinst = new OpCode(OpCodeValues.Isinst,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R_Un = new OpCode(OpCodeValues.Conv_R_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unbox = new OpCode(OpCodeValues.Unbox,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Throw = new OpCode(OpCodeValues.Throw,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Throw << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldfld = new OpCode(OpCodeValues.Ldfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldflda = new OpCode(OpCodeValues.Ldflda,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stfld = new OpCode(OpCodeValues.Stfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldsfld = new OpCode(OpCodeValues.Ldsfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldsflda = new OpCode(OpCodeValues.Ldsflda,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stsfld = new OpCode(OpCodeValues.Stsfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stobj = new OpCode(OpCodeValues.Stobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(OpCodeValues.Conv_Ovf_I1_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(OpCodeValues.Conv_Ovf_I2_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(OpCodeValues.Conv_Ovf_I4_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(OpCodeValues.Conv_Ovf_I8_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(OpCodeValues.Conv_Ovf_U1_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(OpCodeValues.Conv_Ovf_U2_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(OpCodeValues.Conv_Ovf_U4_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(OpCodeValues.Conv_Ovf_U8_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I_Un = new OpCode(OpCodeValues.Conv_Ovf_I_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U_Un = new OpCode(OpCodeValues.Conv_Ovf_U_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Box = new OpCode(OpCodeValues.Box,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Newarr = new OpCode(OpCodeValues.Newarr,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldlen = new OpCode(OpCodeValues.Ldlen,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelema = new OpCode(OpCodeValues.Ldelema,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I1 = new OpCode(OpCodeValues.Ldelem_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U1 = new OpCode(OpCodeValues.Ldelem_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I2 = new OpCode(OpCodeValues.Ldelem_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U2 = new OpCode(OpCodeValues.Ldelem_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I4 = new OpCode(OpCodeValues.Ldelem_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U4 = new OpCode(OpCodeValues.Ldelem_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I8 = new OpCode(OpCodeValues.Ldelem_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I = new OpCode(OpCodeValues.Ldelem_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_R4 = new OpCode(OpCodeValues.Ldelem_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_R8 = new OpCode(OpCodeValues.Ldelem_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_Ref = new OpCode(OpCodeValues.Ldelem_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I = new OpCode(OpCodeValues.Stelem_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I1 = new OpCode(OpCodeValues.Stelem_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I2 = new OpCode(OpCodeValues.Stelem_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I4 = new OpCode(OpCodeValues.Stelem_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I8 = new OpCode(OpCodeValues.Stelem_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_R4 = new OpCode(OpCodeValues.Stelem_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popr4 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_R8 = new OpCode(OpCodeValues.Stelem_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popr8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_Ref = new OpCode(OpCodeValues.Stelem_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem = new OpCode(OpCodeValues.Ldelem,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem = new OpCode(OpCodeValues.Stelem,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unbox_Any = new OpCode(OpCodeValues.Unbox_Any,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I1 = new OpCode(OpCodeValues.Conv_Ovf_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U1 = new OpCode(OpCodeValues.Conv_Ovf_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I2 = new OpCode(OpCodeValues.Conv_Ovf_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U2 = new OpCode(OpCodeValues.Conv_Ovf_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I4 = new OpCode(OpCodeValues.Conv_Ovf_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U4 = new OpCode(OpCodeValues.Conv_Ovf_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I8 = new OpCode(OpCodeValues.Conv_Ovf_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U8 = new OpCode(OpCodeValues.Conv_Ovf_U8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Refanyval = new OpCode(OpCodeValues.Refanyval,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ckfinite = new OpCode(OpCodeValues.Ckfinite,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mkrefany = new OpCode(OpCodeValues.Mkrefany,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldtoken = new OpCode(OpCodeValues.Ldtoken,
+ ((int)OperandType.InlineTok) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U2 = new OpCode(OpCodeValues.Conv_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U1 = new OpCode(OpCodeValues.Conv_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I = new OpCode(OpCodeValues.Conv_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I = new OpCode(OpCodeValues.Conv_Ovf_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U = new OpCode(OpCodeValues.Conv_Ovf_U,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add_Ovf = new OpCode(OpCodeValues.Add_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add_Ovf_Un = new OpCode(OpCodeValues.Add_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul_Ovf = new OpCode(OpCodeValues.Mul_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul_Ovf_Un = new OpCode(OpCodeValues.Mul_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub_Ovf = new OpCode(OpCodeValues.Sub_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub_Ovf_Un = new OpCode(OpCodeValues.Sub_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Endfinally = new OpCode(OpCodeValues.Endfinally,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Leave = new OpCode(OpCodeValues.Leave,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Leave_S = new OpCode(OpCodeValues.Leave_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I = new OpCode(OpCodeValues.Stind_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U = new OpCode(OpCodeValues.Conv_U,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix7 = new OpCode(OpCodeValues.Prefix7,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix6 = new OpCode(OpCodeValues.Prefix6,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix5 = new OpCode(OpCodeValues.Prefix5,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix4 = new OpCode(OpCodeValues.Prefix4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix3 = new OpCode(OpCodeValues.Prefix3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix2 = new OpCode(OpCodeValues.Prefix2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix1 = new OpCode(OpCodeValues.Prefix1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefixref = new OpCode(OpCodeValues.Prefixref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Arglist = new OpCode(OpCodeValues.Arglist,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ceq = new OpCode(OpCodeValues.Ceq,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cgt = new OpCode(OpCodeValues.Cgt,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cgt_Un = new OpCode(OpCodeValues.Cgt_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Clt = new OpCode(OpCodeValues.Clt,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Clt_Un = new OpCode(OpCodeValues.Clt_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldftn = new OpCode(OpCodeValues.Ldftn,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldvirtftn = new OpCode(OpCodeValues.Ldvirtftn,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg = new OpCode(OpCodeValues.Ldarg,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarga = new OpCode(OpCodeValues.Ldarga,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Starg = new OpCode(OpCodeValues.Starg,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc = new OpCode(OpCodeValues.Ldloc,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloca = new OpCode(OpCodeValues.Ldloca,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc = new OpCode(OpCodeValues.Stloc,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Localloc = new OpCode(OpCodeValues.Localloc,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Endfilter = new OpCode(OpCodeValues.Endfilter,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unaligned = new OpCode(OpCodeValues.Unaligned_,
+ ((int)OperandType.ShortInlineI) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Volatile = new OpCode(OpCodeValues.Volatile_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Tailcall = new OpCode(OpCodeValues.Tail_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Initobj = new OpCode(OpCodeValues.Initobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Constrained = new OpCode(OpCodeValues.Constrained_,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cpblk = new OpCode(OpCodeValues.Cpblk,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Initblk = new OpCode(OpCodeValues.Initblk,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rethrow = new OpCode(OpCodeValues.Rethrow,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Throw << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sizeof = new OpCode(OpCodeValues.Sizeof,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Refanytype = new OpCode(OpCodeValues.Refanytype,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Readonly = new OpCode(OpCodeValues.Readonly_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+
+ public static bool TakesSingleByteArgument(OpCode inst)
+ {
+ switch (inst.OperandType)
+ {
+ case OperandType.ShortInlineBrTarget:
+ case OperandType.ShortInlineI:
+ case OperandType.ShortInlineVar:
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs
new file mode 100644
index 000000000..1a144fcf4
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs
@@ -0,0 +1,191 @@
+// 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.Threading;
+
+namespace System.Reflection.Emit
+{
+ public struct OpCode
+ {
+ //
+ // Use packed bitfield for flags to avoid code bloat
+ //
+
+ internal const int OperandTypeMask = 0x1F; // 000000000000000000000000000XXXXX
+
+ internal const int FlowControlShift = 5; // 00000000000000000000000XXXX00000
+ internal const int FlowControlMask = 0x0F;
+
+ internal const int OpCodeTypeShift = 9; // 00000000000000000000XXX000000000
+ internal const int OpCodeTypeMask = 0x07;
+
+ internal const int StackBehaviourPopShift = 12; // 000000000000000XXXXX000000000000
+ internal const int StackBehaviourPushShift = 17; // 0000000000XXXXX00000000000000000
+ internal const int StackBehaviourMask = 0x1F;
+
+ internal const int SizeShift = 22; // 00000000XX0000000000000000000000
+ internal const int SizeMask = 0x03;
+
+ internal const int EndsUncondJmpBlkFlag = 0x01000000; // 0000000X000000000000000000000000
+
+ // unused // 0000XXX0000000000000000000000000
+
+ internal const int StackChangeShift = 28; // XXXX0000000000000000000000000000
+
+ private OpCodeValues m_value;
+ private int m_flags;
+
+ internal OpCode(OpCodeValues value, int flags)
+ {
+ m_value = value;
+ m_flags = flags;
+ }
+
+ internal bool EndsUncondJmpBlk()
+ {
+ return (m_flags & EndsUncondJmpBlkFlag) != 0;
+ }
+
+ internal int StackChange()
+ {
+ return (m_flags >> StackChangeShift);
+ }
+
+ public OperandType OperandType
+ {
+ get
+ {
+ return (OperandType)(m_flags & OperandTypeMask);
+ }
+ }
+
+ public FlowControl FlowControl
+ {
+ get
+ {
+ return (FlowControl)((m_flags >> FlowControlShift) & FlowControlMask);
+ }
+ }
+
+ public OpCodeType OpCodeType
+ {
+ get
+ {
+ return (OpCodeType)((m_flags >> OpCodeTypeShift) & OpCodeTypeMask);
+ }
+ }
+
+ public StackBehaviour StackBehaviourPop
+ {
+ get
+ {
+ return (StackBehaviour)((m_flags >> StackBehaviourPopShift) & StackBehaviourMask);
+ }
+ }
+
+ public StackBehaviour StackBehaviourPush
+ {
+ get
+ {
+ return (StackBehaviour)((m_flags >> StackBehaviourPushShift) & StackBehaviourMask);
+ }
+ }
+
+ public int Size
+ {
+ get
+ {
+ return (m_flags >> SizeShift) & SizeMask;
+ }
+ }
+
+ public short Value
+ {
+ get
+ {
+ return (short)m_value;
+ }
+ }
+
+ private static volatile string[] g_nameCache;
+
+ public string Name
+ {
+ get
+ {
+ if (Size == 0)
+ return null;
+
+ // Create and cache the opcode names lazily. They should be rarely used (only for logging, etc.)
+ // Note that we do not any locks here because of we always get the same names. The last one wins.
+ string[] nameCache = g_nameCache;
+ if (nameCache == null)
+ {
+ nameCache = new string[0x11f];
+ g_nameCache = nameCache;
+ }
+
+ OpCodeValues opCodeValue = (OpCodeValues)(ushort)Value;
+
+ int idx = (int)opCodeValue;
+ if (idx > 0xFF)
+ {
+ if (idx >= 0xfe00 && idx <= 0xfe1e)
+ {
+ // Transform two byte opcode value to lower range that's suitable
+ // for array index
+ idx = 0x100 + (idx - 0xfe00);
+ }
+ else
+ {
+ // Unknown opcode
+ return null;
+ }
+ }
+
+ string name = Volatile.Read(ref nameCache[idx]);
+ if (name != null)
+ return name;
+
+ // Create ilasm style name from the enum value name.
+ name = Enum.GetName(typeof(OpCodeValues), opCodeValue).ToLowerInvariant().Replace("_", ".");
+ Volatile.Write(ref nameCache[idx], name);
+ return name;
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is OpCode)
+ return Equals((OpCode)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(OpCode obj)
+ {
+ return obj.Value == Value;
+ }
+
+ public static bool operator ==(OpCode a, OpCode b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(OpCode a, OpCode b)
+ {
+ return !(a == b);
+ }
+
+ public override int GetHashCode()
+ {
+ return Value;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs
new file mode 100644
index 000000000..6257c5674
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs
@@ -0,0 +1,41 @@
+// 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.
+
+/*============================================================
+**
+** Enumeration: OperandType
+**
+** Purpose: Exposes OperandType Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum OperandType
+ {
+ InlineBrTarget = 0,
+ InlineField = 1,
+ InlineI = 2,
+ InlineI8 = 3,
+ InlineMethod = 4,
+ InlineNone = 5,
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ InlinePhi = 6,
+ InlineR = 7,
+ InlineSig = 9,
+ InlineString = 10,
+ InlineSwitch = 11,
+ InlineTok = 12,
+ InlineType = 13,
+ InlineVar = 14,
+ ShortInlineBrTarget = 15,
+ ShortInlineI = 16,
+ ShortInlineR = 17,
+ ShortInlineVar = 18,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs
new file mode 100644
index 000000000..f6606c477
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs
@@ -0,0 +1,17 @@
+// 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;
+
+namespace System.Reflection.Emit
+{
+ // This Enum matchs the CorFieldAttr defined in CorHdr.h
+ public enum PEFileKinds
+ {
+ Dll = 0x0001,
+ ConsoleApplication = 0x0002,
+ WindowApplication = 0x0003,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs
new file mode 100644
index 000000000..f734e1a34
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs
@@ -0,0 +1,19 @@
+// 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.
+
+namespace System.Reflection.Emit
+{
+ public enum PackingSize
+ {
+ Unspecified = 0,
+ Size1 = 1,
+ Size2 = 2,
+ Size4 = 4,
+ Size8 = 8,
+ Size16 = 16,
+ Size32 = 32,
+ Size64 = 64,
+ Size128 = 128,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs
new file mode 100644
index 000000000..3e64b4879
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs
@@ -0,0 +1,51 @@
+// 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.
+
+/*============================================================
+**
+** Enumeration: StackBehaviour
+**
+** Purpose: Exposes StackBehaviour Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum StackBehaviour
+ {
+ Pop0 = 0,
+ Pop1 = 1,
+ Pop1_pop1 = 2,
+ Popi = 3,
+ Popi_pop1 = 4,
+ Popi_popi = 5,
+ Popi_popi8 = 6,
+ Popi_popi_popi = 7,
+ Popi_popr4 = 8,
+ Popi_popr8 = 9,
+ Popref = 10,
+ Popref_pop1 = 11,
+ Popref_popi = 12,
+ Popref_popi_popi = 13,
+ Popref_popi_popi8 = 14,
+ Popref_popi_popr4 = 15,
+ Popref_popi_popr8 = 16,
+ Popref_popi_popref = 17,
+ Push0 = 18,
+ Push1 = 19,
+ Push1_push1 = 20,
+ Pushi = 21,
+ Pushi8 = 22,
+ Pushr4 = 23,
+ Pushr8 = 24,
+ Pushref = 25,
+ Varpop = 26,
+ Varpush = 27,
+ Popref_popi_pop1 = 28,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs
new file mode 100644
index 000000000..15780f11c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs
@@ -0,0 +1,28 @@
+// 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.Globalization;
+
+namespace System.Reflection
+{
+ public class ExceptionHandlingClause
+ {
+ protected ExceptionHandlingClause() { }
+ public virtual ExceptionHandlingClauseOptions Flags => default;
+ public virtual int TryOffset => 0;
+ public virtual int TryLength => 0;
+ public virtual int HandlerOffset => 0;
+ public virtual int HandlerLength => 0;
+ public virtual int FilterOffset => throw new InvalidOperationException(SR.Arg_EHClauseNotFilter);
+ public virtual Type CatchType => null;
+
+ public override string ToString()
+ {
+ return string.Format(CultureInfo.CurrentUICulture,
+ "Flags={0}, TryOffset={1}, TryLength={2}, HandlerOffset={3}, HandlerLength={4}, CatchType={5}",
+ Flags, TryOffset, TryLength, HandlerOffset, HandlerLength, CatchType);
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs
new file mode 100644
index 000000000..1540bde53
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs
@@ -0,0 +1,26 @@
+// 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.Diagnostics;
+
+namespace System.Reflection
+{
+ public class LocalVariableInfo
+ {
+ public virtual Type LocalType { get { Debug.Fail("type must be set!"); return null; } }
+ public virtual int LocalIndex => 0;
+ public virtual bool IsPinned => false;
+ protected LocalVariableInfo() { }
+ public override string ToString()
+ {
+ string toString = LocalType.ToString() + " (" + LocalIndex + ")";
+
+ if (IsPinned)
+ toString += " (pinned)";
+
+ return toString;
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs b/src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs
new file mode 100644
index 000000000..bdf53ad12
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs
@@ -0,0 +1,20 @@
+// 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.Collections.Generic;
+
+namespace System.Reflection
+{
+ public class MethodBody
+ {
+ protected MethodBody() { }
+ public virtual int LocalSignatureMetadataToken => 0;
+ public virtual IList<LocalVariableInfo> LocalVariables => throw new ArgumentNullException("array");
+ public virtual int MaxStackSize => 0;
+ public virtual bool InitLocals => false;
+ public virtual byte[] GetILAsByteArray() => null;
+ public virtual IList<ExceptionHandlingClause> ExceptionHandlingClauses => throw new ArgumentNullException("array");
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Module.cs b/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
index 56f83c40d..d290f7803 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
@@ -130,53 +130,29 @@ namespace System.Reflection
public override string ToString() => ScopeName;
- public static readonly TypeFilter FilterTypeName = FilterTypeNameImpl;
- public static readonly TypeFilter FilterTypeNameIgnoreCase = FilterTypeNameIgnoreCaseImpl;
+ public static readonly TypeFilter FilterTypeName = (m, c) => FilterTypeNameImpl(m, c, StringComparison.Ordinal);
+ public static readonly TypeFilter FilterTypeNameIgnoreCase = (m, c) => FilterTypeNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
// FilterTypeName
// This method will filter the class based upon the name. It supports
// a trailing wild card.
- private static bool FilterTypeNameImpl(Type cls, object filterCriteria)
+ private static bool FilterTypeNameImpl(Type cls, object filterCriteria, StringComparison comparison)
{
// Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
- throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
-
- // Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[str.Length - 1] == '*')
+ if (!(filterCriteria is string str))
{
- str = str.Substring(0, str.Length - 1);
- return cls.Name.StartsWith(str, StringComparison.Ordinal);
- }
-
- return cls.Name.Equals(str);
- }
-
- // FilterFieldNameIgnoreCase
- // This method filter the Type based upon name, it ignores case.
- private static bool FilterTypeNameIgnoreCaseImpl(Type cls, object filterCriteria)
- {
- // Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
-
+ }
// Check to see if this is a prefix or exact match requirement
if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- string name = cls.Name;
- if (name.Length >= str.Length)
- return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0);
- else
- return false;
+ ReadOnlySpan<char> slice = str.AsSpan(0, str.Length - 1);
+ return cls.Name.AsSpan().StartsWith(slice, comparison);
}
- return (string.Compare(str, cls.Name, StringComparison.OrdinalIgnoreCase) == 0);
+
+ return cls.Name.Equals(str, comparison);
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs b/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs
index cd97ffa21..d3d88520f 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs
@@ -10,11 +10,25 @@ namespace System.Reflection
{
internal sealed class SignatureConstructedGenericType : SignatureType
{
- internal SignatureConstructedGenericType(Type genericTypeDefinition, Type[] genericTypeArguments)
+ // The exception-visible name "typeArguments" is chosen to match the parameter name to Type.MakeGenericType() since that's the
+ // intended user of this constructor.
+ internal SignatureConstructedGenericType(Type genericTypeDefinition, Type[] typeArguments)
{
- Debug.Assert(genericTypeDefinition != null && genericTypeArguments != null);
+ if (genericTypeDefinition == null)
+ throw new ArgumentNullException(nameof(genericTypeDefinition));
+
+ if (typeArguments == null)
+ throw new ArgumentNullException(nameof(typeArguments));
+
+ typeArguments = (Type[])(typeArguments.Clone());
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ if (typeArguments[i] == null)
+ throw new ArgumentNullException(nameof(typeArguments));
+ }
+
_genericTypeDefinition = genericTypeDefinition;
- _genericTypeArguments = (Type[])(genericTypeArguments.Clone());
+ _genericTypeArguments = typeArguments;
}
public sealed override bool IsTypeDefinition => false;
diff --git a/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs b/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs
new file mode 100644
index 000000000..6b813a0ce
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs
@@ -0,0 +1,142 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A collection of quick methods for comparing
+** resource keys (strings)
+**
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Resources
+{
+ internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<string>, IEqualityComparer<string>
+ {
+ internal static readonly FastResourceComparer Default = new FastResourceComparer();
+
+ // Implements IHashCodeProvider too, due to Hashtable requirements.
+ public int GetHashCode(object key)
+ {
+ string s = (string)key;
+ return FastResourceComparer.HashFunction(s);
+ }
+
+ public int GetHashCode(string key)
+ {
+ return FastResourceComparer.HashFunction(key);
+ }
+
+ // This hash function MUST be publically documented with the resource
+ // file format, AND we may NEVER change this hash function's return
+ // value (without changing the file format).
+ internal static int HashFunction(string key)
+ {
+ // Never change this hash function. We must standardize it so that
+ // others can read & write our .resources files. Additionally, we
+ // have a copy of it in InternalResGen as well.
+ uint hash = 5381;
+ for (int i = 0; i < key.Length; i++)
+ hash = ((hash << 5) + hash) ^ key[i];
+ return (int)hash;
+ }
+
+ // Compares Strings quickly in a case-sensitive way
+ public int Compare(object a, object b)
+ {
+ if (a == b) return 0;
+ string sa = (string)a;
+ string sb = (string)b;
+ return string.CompareOrdinal(sa, sb);
+ }
+
+ public int Compare(string a, string b)
+ {
+ return string.CompareOrdinal(a, b);
+ }
+
+ public bool Equals(string a, string b)
+ {
+ return string.Equals(a, b);
+ }
+
+ public new bool Equals(object a, object b)
+ {
+ if (a == b) return true;
+ string sa = (string)a;
+ string sb = (string)b;
+ return string.Equals(sa, sb);
+ }
+
+ // Input is one string to compare with, and a byte[] containing chars in
+ // little endian unicode. Pass in the number of valid chars.
+ public static unsafe int CompareOrdinal(string a, byte[] bytes, int bCharLength)
+ {
+ Debug.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params");
+ Debug.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!");
+ // This is a managed version of strcmp, but I can't take advantage
+ // of a terminating 0, unlike strcmp in C.
+ int i = 0;
+ int r = 0;
+ // Compare the min length # of characters, then return length diffs.
+ int numChars = a.Length;
+ if (numChars > bCharLength)
+ numChars = bCharLength;
+ if (bCharLength == 0) // Can't use fixed on a 0-element array.
+ return (a.Length == 0) ? 0 : -1;
+ fixed (byte* pb = bytes)
+ {
+ byte* pChar = pb;
+ while (i < numChars && r == 0)
+ {
+ // little endian format
+ int b = pChar[0] | pChar[1] << 8;
+ r = a[i++] - b;
+ pChar += sizeof(char);
+ }
+ }
+ if (r != 0) return r;
+ return a.Length - bCharLength;
+ }
+
+ public static int CompareOrdinal(byte[] bytes, int aCharLength, string b)
+ {
+ return -CompareOrdinal(b, bytes, aCharLength);
+ }
+
+ // This method is to handle potentially misaligned data accesses.
+ // The byte* must point to little endian Unicode characters.
+ internal static unsafe int CompareOrdinal(byte* a, int byteLen, string b)
+ {
+ Debug.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!");
+ Debug.Assert(a != null && b != null, "Null args not allowed.");
+ Debug.Assert(byteLen >= 0, "byteLen must be non-negative.");
+
+ int r = 0;
+ int i = 0;
+ // Compare the min length # of characters, then return length diffs.
+ int numChars = byteLen >> 1;
+ if (numChars > b.Length)
+ numChars = b.Length;
+ while (i < numChars && r == 0)
+ {
+ // Must compare character by character, not byte by byte.
+ char aCh = (char)(*a++ | (*a++ << 8));
+ r = aCh - b[i++];
+ }
+ if (r != 0) return r;
+ return byteLen - b.Length * 2;
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs b/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs
index af547b21f..0bbc62673 100644
--- a/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs
@@ -24,7 +24,7 @@ namespace System.Resources
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class MissingSatelliteAssemblyException : SystemException
{
- private String _cultureName;
+ private string _cultureName;
public MissingSatelliteAssemblyException()
: base(SR.MissingSatelliteAssembly_Default)
@@ -38,7 +38,7 @@ namespace System.Resources
HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
}
- public MissingSatelliteAssemblyException(string message, String cultureName)
+ public MissingSatelliteAssemblyException(string message, string cultureName)
: base(message)
{
HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
@@ -56,7 +56,7 @@ namespace System.Resources
{
}
- public String CultureName
+ public string CultureName
{
get { return _cultureName; }
}
diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs
new file mode 100644
index 000000000..cd2b0d080
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs
@@ -0,0 +1,1184 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Default way to read streams of resources on
+** demand.
+**
+** Version 2 support on October 6, 2003
+**
+===========================================================*/
+
+namespace System.Resources
+{
+ using System;
+ using System.IO;
+ using System.Text;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Security;
+ using System.Globalization;
+ using System.Configuration.Assemblies;
+ using System.Runtime.Versioning;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ // Provides the default implementation of IResourceReader, reading
+ // .resources file from the system default binary format. This class
+ // can be treated as an enumerator once.
+ //
+ // See the RuntimeResourceSet overview for details on the system
+ // default file format.
+ //
+
+ internal struct ResourceLocator
+ {
+ internal object _value; // Can be null. Consider WeakReference instead?
+ internal int _dataPos;
+
+ internal ResourceLocator(int dataPos, object value)
+ {
+ _dataPos = dataPos;
+ _value = value;
+ }
+
+ internal int DataPosition
+ {
+ get { return _dataPos; }
+ //set { _dataPos = value; }
+ }
+
+ // Allows adding in profiling data in a future version, or a special
+ // resource profiling build. We could also use WeakReference.
+ internal object Value
+ {
+ get { return _value; }
+ set { _value = value; }
+ }
+
+ internal static bool CanCache(ResourceTypeCode value)
+ {
+ Debug.Assert(value >= 0, "negative ResourceTypeCode. What?");
+ return value <= ResourceTypeCode.LastPrimitive;
+ }
+ }
+
+ public sealed class ResourceReader : IResourceReader
+ {
+ // A reasonable default buffer size for reading from files, especially
+ // when we will likely be seeking frequently. Could be smaller, but does
+ // it make sense to use anything less than one page?
+ private const int DefaultFileStreamBufferSize = 4096;
+
+ private BinaryReader _store; // backing store we're reading from.
+ // Used by RuntimeResourceSet and this class's enumerator. Maps
+ // resource name to a value, a ResourceLocator, or a
+ // LooselyLinkedManifestResource.
+ internal Dictionary<string, ResourceLocator> _resCache;
+ private long _nameSectionOffset; // Offset to name section of file.
+ private long _dataSectionOffset; // Offset to Data section of file.
+
+ // Note this class is tightly coupled with UnmanagedMemoryStream.
+ // At runtime when getting an embedded resource from an assembly,
+ // we're given an UnmanagedMemoryStream referring to the mmap'ed portion
+ // of the assembly. The pointers here are pointers into that block of
+ // memory controlled by the OS's loader.
+ private int[] _nameHashes; // hash values for all names.
+ private unsafe int* _nameHashesPtr; // In case we're using UnmanagedMemoryStream
+ private int[] _namePositions; // relative locations of names
+ private unsafe int* _namePositionsPtr; // If we're using UnmanagedMemoryStream
+ private Type[] _typeTable; // Lazy array of Types for resource values.
+ private int[] _typeNamePositions; // To delay initialize type table
+ private int _numResources; // Num of resources files, in case arrays aren't allocated.
+
+ // We'll include a separate code path that uses UnmanagedMemoryStream to
+ // avoid allocating String objects and the like.
+ private UnmanagedMemoryStream _ums;
+
+ // Version number of .resources file, for compatibility
+ private int _version;
+
+
+ public ResourceReader(string fileName)
+ {
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
+ _store = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.RandomAccess), Encoding.UTF8);
+
+ try
+ {
+ ReadResources();
+ }
+ catch
+ {
+ _store.Close(); // If we threw an exception, close the file.
+ throw;
+ }
+ }
+
+ public ResourceReader(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+ if (!stream.CanRead)
+ throw new ArgumentException(SR.Argument_StreamNotReadable);
+
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
+ _store = new BinaryReader(stream, Encoding.UTF8);
+ // We have a faster code path for reading resource files from an assembly.
+ _ums = stream as UnmanagedMemoryStream;
+
+ ReadResources();
+ }
+
+ // This is the constructor the RuntimeResourceSet calls,
+ // passing in the stream to read from and the RuntimeResourceSet's
+ // internal hash table (hash table of names with file offsets
+ // and values, coupled to this ResourceReader).
+ internal ResourceReader(Stream stream, Dictionary<string, ResourceLocator> resCache)
+ {
+ Debug.Assert(stream != null, "Need a stream!");
+ Debug.Assert(stream.CanRead, "Stream should be readable!");
+ Debug.Assert(resCache != null, "Need a Dictionary!");
+
+ _resCache = resCache;
+ _store = new BinaryReader(stream, Encoding.UTF8);
+
+ _ums = stream as UnmanagedMemoryStream;
+
+ ReadResources();
+ }
+
+
+ public void Close()
+ {
+ Dispose(true);
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ private unsafe void Dispose(bool disposing)
+ {
+ if (_store != null)
+ {
+ _resCache = null;
+ if (disposing)
+ {
+ // Close the stream in a thread-safe way. This fix means
+ // that we may call Close n times, but that's safe.
+ BinaryReader copyOfStore = _store;
+ _store = null;
+ if (copyOfStore != null)
+ copyOfStore.Close();
+ }
+ _store = null;
+ _namePositions = null;
+ _nameHashes = null;
+ _ums = null;
+ _namePositionsPtr = null;
+ _nameHashesPtr = null;
+ }
+ }
+
+ internal static unsafe int ReadUnalignedI4(int* p)
+ {
+ byte* buffer = (byte*)p;
+ // Unaligned, little endian format
+ return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ }
+
+
+ private void SkipString()
+ {
+ int stringLength = _store.Read7BitEncodedInt();
+ if (stringLength < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_NegativeStringLength);
+ }
+ _store.BaseStream.Seek(stringLength, SeekOrigin.Current);
+ }
+
+ private unsafe int GetNameHash(int index)
+ {
+ Debug.Assert(index >= 0 && index < _numResources, "Bad index into hash array. index: " + index);
+ Debug.Assert((_ums == null && _nameHashes != null && _nameHashesPtr == null) ||
+ (_ums != null && _nameHashes == null && _nameHashesPtr != null), "Internal state mangled.");
+ if (_ums == null)
+ return _nameHashes[index];
+ else
+ return ReadUnalignedI4(&_nameHashesPtr[index]);
+ }
+
+ private unsafe int GetNamePosition(int index)
+ {
+ Debug.Assert(index >= 0 && index < _numResources, "Bad index into name position array. index: " + index);
+ Debug.Assert((_ums == null && _namePositions != null && _namePositionsPtr == null) ||
+ (_ums != null && _namePositions == null && _namePositionsPtr != null), "Internal state mangled.");
+ int r;
+ if (_ums == null)
+ r = _namePositions[index];
+ else
+ r = ReadUnalignedI4(&_namePositionsPtr[index]);
+ if (r < 0 || r > _dataSectionOffset - _nameSectionOffset)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesNameInvalidOffset, r));
+ }
+ return r;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IDictionaryEnumerator GetEnumerator()
+ {
+ if (_resCache == null)
+ throw new InvalidOperationException(SR.ResourceReaderIsClosed);
+ return new ResourceEnumerator(this);
+ }
+
+ internal ResourceEnumerator GetEnumeratorInternal()
+ {
+ return new ResourceEnumerator(this);
+ }
+
+ // From a name, finds the associated virtual offset for the data.
+ // To read the data, seek to _dataSectionOffset + dataPos, then
+ // read the resource type & data.
+ // This does a binary search through the names.
+ internal int FindPosForResource(string name)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ int hash = FastResourceComparer.HashFunction(name);
+
+ // Binary search over the hashes. Use the _namePositions array to
+ // determine where they exist in the underlying stream.
+ int lo = 0;
+ int hi = _numResources - 1;
+ int index = -1;
+ bool success = false;
+ while (lo <= hi)
+ {
+ index = (lo + hi) >> 1;
+ // Do NOT use subtraction here, since it will wrap for large
+ // negative numbers.
+ int currentHash = GetNameHash(index);
+ int c;
+ if (currentHash == hash)
+ c = 0;
+ else if (currentHash < hash)
+ c = -1;
+ else
+ c = 1;
+
+ if (c == 0)
+ {
+ success = true;
+ break;
+ }
+ if (c < 0)
+ lo = index + 1;
+ else
+ hi = index - 1;
+ }
+ if (!success)
+ {
+ return -1;
+ }
+
+ // index is the location in our hash array that corresponds with a
+ // value in the namePositions array.
+ // There could be collisions in our hash function. Check on both sides
+ // of index to find the range of hash values that are equal to the
+ // target hash value.
+ if (lo != index)
+ {
+ lo = index;
+ while (lo > 0 && GetNameHash(lo - 1) == hash)
+ lo--;
+ }
+ if (hi != index)
+ {
+ hi = index;
+ while (hi < _numResources - 1 && GetNameHash(hi + 1) == hash)
+ hi++;
+ }
+
+ lock (this)
+ {
+ for (int i = lo; i <= hi; i++)
+ {
+ _store.BaseStream.Seek(_nameSectionOffset + GetNamePosition(i), SeekOrigin.Begin);
+ if (CompareStringEqualsName(name))
+ {
+ int dataPos = _store.ReadInt32();
+ if (dataPos < 0 || dataPos >= _store.BaseStream.Length - _dataSectionOffset)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesDataInvalidOffset, dataPos));
+ }
+ return dataPos;
+ }
+ }
+ }
+ return -1;
+ }
+
+ // This compares the String in the .resources file at the current position
+ // with the string you pass in.
+ // Whoever calls this method should make sure that they take a lock
+ // so no one else can cause us to seek in the stream.
+ private unsafe bool CompareStringEqualsName(string name)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ int byteLen = _store.Read7BitEncodedInt();
+ if (byteLen < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_NegativeStringLength);
+ }
+ if (_ums != null)
+ {
+ byte* bytes = _ums.PositionPointer;
+ // Skip over the data in the Stream, positioning ourselves right after it.
+ _ums.Seek(byteLen, SeekOrigin.Current);
+ if (_ums.Position > _ums.Length)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesNameTooLong);
+ }
+
+ // On 64-bit machines, these char*'s may be misaligned. Use a
+ // byte-by-byte comparison instead.
+ //return FastResourceComparer.CompareOrdinal((char*)bytes, byteLen/2, name) == 0;
+ return FastResourceComparer.CompareOrdinal(bytes, byteLen, name) == 0;
+ }
+ else
+ {
+ // This code needs to be fast
+ byte[] bytes = new byte[byteLen];
+ int numBytesToRead = byteLen;
+ while (numBytesToRead > 0)
+ {
+ int n = _store.Read(bytes, byteLen - numBytesToRead, numBytesToRead);
+ if (n == 0)
+ throw new BadImageFormatException(SR.BadImageFormat_ResourceNameCorrupted);
+ numBytesToRead -= n;
+ }
+ return FastResourceComparer.CompareOrdinal(bytes, byteLen / 2, name) == 0;
+ }
+ }
+
+ // This is used in the enumerator. The enumerator iterates from 0 to n
+ // of our resources and this returns the resource name for a particular
+ // index. The parameter is NOT a virtual offset.
+ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ byte[] bytes;
+ int byteLen;
+ long nameVA = GetNamePosition(index);
+ lock (this)
+ {
+ _store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin);
+ // Can't use _store.ReadString, since it's using UTF-8!
+ byteLen = _store.Read7BitEncodedInt();
+ if (byteLen < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_NegativeStringLength);
+ }
+
+ if (_ums != null)
+ {
+ if (_ums.Position > _ums.Length - byteLen)
+ throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourcesIndexTooLong, index));
+
+ string s = null;
+ char* charPtr = (char*)_ums.PositionPointer;
+
+ s = new string(charPtr, 0, byteLen / 2);
+
+ _ums.Position += byteLen;
+ dataOffset = _store.ReadInt32();
+ if (dataOffset < 0 || dataOffset >= _store.BaseStream.Length - _dataSectionOffset)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesDataInvalidOffset, dataOffset));
+ }
+ return s;
+ }
+
+ bytes = new byte[byteLen];
+ // We must read byteLen bytes, or we have a corrupted file.
+ // Use a blocking read in case the stream doesn't give us back
+ // everything immediately.
+ int count = byteLen;
+ while (count > 0)
+ {
+ int n = _store.Read(bytes, byteLen - count, count);
+ if (n == 0)
+ throw new EndOfStreamException(SR.Format(SR.BadImageFormat_ResourceNameCorrupted_NameIndex, index));
+ count -= n;
+ }
+ dataOffset = _store.ReadInt32();
+ if (dataOffset < 0 || dataOffset >= _store.BaseStream.Length - _dataSectionOffset)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesDataInvalidOffset, dataOffset));
+ }
+ }
+ return Encoding.Unicode.GetString(bytes, 0, byteLen);
+ }
+
+ // This is used in the enumerator. The enumerator iterates from 0 to n
+ // of our resources and this returns the resource value for a particular
+ // index. The parameter is NOT a virtual offset.
+ private object GetValueForNameIndex(int index)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ long nameVA = GetNamePosition(index);
+ lock (this)
+ {
+ _store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin);
+ SkipString();
+
+ int dataPos = _store.ReadInt32();
+ if (dataPos < 0 || dataPos >= _store.BaseStream.Length - _dataSectionOffset)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesDataInvalidOffset, dataPos));
+ }
+ ResourceTypeCode junk;
+ if (_version == 1)
+ return LoadObjectV1(dataPos);
+ else
+ return LoadObjectV2(dataPos, out junk);
+ }
+ }
+
+ // This takes a virtual offset into the data section and reads a String
+ // from that location.
+ // Anyone who calls LoadObject should make sure they take a lock so
+ // no one can cause us to do a seek in here.
+ internal string LoadString(int pos)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin);
+ string s = null;
+ int typeIndex = _store.Read7BitEncodedInt();
+ if (_version == 1)
+ {
+ if (typeIndex == -1)
+ return null;
+ if (FindType(typeIndex) != typeof(string))
+ throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, FindType(typeIndex).FullName));
+ s = _store.ReadString();
+ }
+ else
+ {
+ ResourceTypeCode typeCode = (ResourceTypeCode)typeIndex;
+ if (typeCode != ResourceTypeCode.String && typeCode != ResourceTypeCode.Null)
+ {
+ string typeString;
+ if (typeCode < ResourceTypeCode.StartOfUserTypes)
+ typeString = typeCode.ToString();
+ else
+ typeString = FindType(typeCode - ResourceTypeCode.StartOfUserTypes).FullName;
+ throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, typeString));
+ }
+ if (typeCode == ResourceTypeCode.String) // ignore Null
+ s = _store.ReadString();
+ }
+ return s;
+ }
+
+ // Called from RuntimeResourceSet
+ internal object LoadObject(int pos)
+ {
+ if (_version == 1)
+ return LoadObjectV1(pos);
+ ResourceTypeCode typeCode;
+ return LoadObjectV2(pos, out typeCode);
+ }
+
+ internal object LoadObject(int pos, out ResourceTypeCode typeCode)
+ {
+ if (_version == 1)
+ {
+ object o = LoadObjectV1(pos);
+ typeCode = (o is string) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes;
+ return o;
+ }
+ return LoadObjectV2(pos, out typeCode);
+ }
+
+ // This takes a virtual offset into the data section and reads an Object
+ // from that location.
+ // Anyone who calls LoadObject should make sure they take a lock so
+ // no one can cause us to do a seek in here.
+ internal object LoadObjectV1(int pos)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ Debug.Assert(_version == 1, ".resources file was not a V1 .resources file!");
+
+ try
+ {
+ // mega try-catch performs exceptionally bad on x64; factored out body into
+ // _LoadObjectV1 and wrap here.
+ return _LoadObjectV1(pos);
+ }
+ catch (EndOfStreamException eof)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_TypeMismatch, eof);
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_TypeMismatch, e);
+ }
+ }
+
+ private object _LoadObjectV1(int pos)
+ {
+ _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin);
+ int typeIndex = _store.Read7BitEncodedInt();
+ if (typeIndex == -1)
+ return null;
+ Type type = FindType(typeIndex);
+ // Consider putting in logic to see if this type is a
+ // primitive or a value type first, so we can reach the
+ // deserialization code faster for arbitrary objects.
+
+ if (type == typeof(string))
+ return _store.ReadString();
+ else if (type == typeof(int))
+ return _store.ReadInt32();
+ else if (type == typeof(byte))
+ return _store.ReadByte();
+ else if (type == typeof(sbyte))
+ return _store.ReadSByte();
+ else if (type == typeof(short))
+ return _store.ReadInt16();
+ else if (type == typeof(long))
+ return _store.ReadInt64();
+ else if (type == typeof(ushort))
+ return _store.ReadUInt16();
+ else if (type == typeof(uint))
+ return _store.ReadUInt32();
+ else if (type == typeof(ulong))
+ return _store.ReadUInt64();
+ else if (type == typeof(float))
+ return _store.ReadSingle();
+ else if (type == typeof(double))
+ return _store.ReadDouble();
+ else if (type == typeof(DateTime))
+ {
+ // Ideally we should use DateTime's ToBinary & FromBinary,
+ // but we can't for compatibility reasons.
+ return new DateTime(_store.ReadInt64());
+ }
+ else if (type == typeof(TimeSpan))
+ return new TimeSpan(_store.ReadInt64());
+ else if (type == typeof(decimal))
+ {
+ int[] bits = new int[4];
+ for (int i = 0; i < bits.Length; i++)
+ bits[i] = _store.ReadInt32();
+ return new decimal(bits);
+ }
+ else
+ {
+ throw new NotSupportedException(SR.NotSupported_ResourceObjectSerialization);
+ }
+ }
+
+ internal object LoadObjectV2(int pos, out ResourceTypeCode typeCode)
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+ Debug.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!");
+
+ try
+ {
+ // mega try-catch performs exceptionally bad on x64; factored out body into
+ // _LoadObjectV2 and wrap here.
+ return _LoadObjectV2(pos, out typeCode);
+ }
+ catch (EndOfStreamException eof)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_TypeMismatch, eof);
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_TypeMismatch, e);
+ }
+ }
+
+ private object _LoadObjectV2(int pos, out ResourceTypeCode typeCode)
+ {
+ _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin);
+ typeCode = (ResourceTypeCode)_store.Read7BitEncodedInt();
+
+ switch (typeCode)
+ {
+ case ResourceTypeCode.Null:
+ return null;
+
+ case ResourceTypeCode.String:
+ return _store.ReadString();
+
+ case ResourceTypeCode.Boolean:
+ return _store.ReadBoolean();
+
+ case ResourceTypeCode.Char:
+ return (char)_store.ReadUInt16();
+
+ case ResourceTypeCode.Byte:
+ return _store.ReadByte();
+
+ case ResourceTypeCode.SByte:
+ return _store.ReadSByte();
+
+ case ResourceTypeCode.Int16:
+ return _store.ReadInt16();
+
+ case ResourceTypeCode.UInt16:
+ return _store.ReadUInt16();
+
+ case ResourceTypeCode.Int32:
+ return _store.ReadInt32();
+
+ case ResourceTypeCode.UInt32:
+ return _store.ReadUInt32();
+
+ case ResourceTypeCode.Int64:
+ return _store.ReadInt64();
+
+ case ResourceTypeCode.UInt64:
+ return _store.ReadUInt64();
+
+ case ResourceTypeCode.Single:
+ return _store.ReadSingle();
+
+ case ResourceTypeCode.Double:
+ return _store.ReadDouble();
+
+ case ResourceTypeCode.Decimal:
+ return _store.ReadDecimal();
+
+ case ResourceTypeCode.DateTime:
+ // Use DateTime's ToBinary & FromBinary.
+ long data = _store.ReadInt64();
+ return DateTime.FromBinary(data);
+
+ case ResourceTypeCode.TimeSpan:
+ long ticks = _store.ReadInt64();
+ return new TimeSpan(ticks);
+
+ // Special types
+ case ResourceTypeCode.ByteArray:
+ {
+ int len = _store.ReadInt32();
+ if (len < 0)
+ {
+ throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourceDataLengthInvalid, len));
+ }
+
+ if (_ums == null)
+ {
+ if (len > _store.BaseStream.Length)
+ {
+ throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourceDataLengthInvalid, len));
+ }
+ return _store.ReadBytes(len);
+ }
+
+ if (len > _ums.Length - _ums.Position)
+ {
+ throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourceDataLengthInvalid, len));
+ }
+
+ byte[] bytes = new byte[len];
+ int r = _ums.Read(bytes, 0, len);
+ Debug.Assert(r == len, "ResourceReader needs to use a blocking read here. (Call _store.ReadBytes(len)?)");
+ return bytes;
+ }
+
+ case ResourceTypeCode.Stream:
+ {
+ int len = _store.ReadInt32();
+ if (len < 0)
+ {
+ throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourceDataLengthInvalid, len));
+ }
+ if (_ums == null)
+ {
+ byte[] bytes = _store.ReadBytes(len);
+ // Lifetime of memory == lifetime of this stream.
+ return new PinnedBufferMemoryStream(bytes);
+ }
+
+ // make sure we don't create an UnmanagedMemoryStream that is longer than the resource stream.
+ if (len > _ums.Length - _ums.Position)
+ {
+ throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourceDataLengthInvalid, len));
+ }
+
+ // For the case that we've memory mapped in the .resources
+ // file, just return a Stream pointing to that block of memory.
+ unsafe
+ {
+ return new UnmanagedMemoryStream(_ums.PositionPointer, len, len, FileAccess.Read);
+ }
+ }
+
+ default:
+ if (typeCode < ResourceTypeCode.StartOfUserTypes)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_TypeMismatch);
+ }
+ break;
+ }
+
+ // Normal serialized objects
+ throw new NotSupportedException(SR.NotSupported_ResourceObjectSerialization);
+ }
+
+ // Reads in the header information for a .resources file. Verifies some
+ // of the assumptions about this resource set, and builds the class table
+ // for the default resource file format.
+ private void ReadResources()
+ {
+ Debug.Assert(_store != null, "ResourceReader is closed!");
+
+ try
+ {
+ // mega try-catch performs exceptionally bad on x64; factored out body into
+ // _ReadResources and wrap here.
+ _ReadResources();
+ }
+ catch (EndOfStreamException eof)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted, eof);
+ }
+ catch (IndexOutOfRangeException e)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted, e);
+ }
+ }
+
+ private void _ReadResources()
+ {
+ // Read ResourceManager header
+ // Check for magic number
+ int magicNum = _store.ReadInt32();
+ if (magicNum != ResourceManager.MagicNumber)
+ throw new ArgumentException(SR.Resources_StreamNotValid);
+ // Assuming this is ResourceManager header V1 or greater, hopefully
+ // after the version number there is a number of bytes to skip
+ // to bypass the rest of the ResMgr header. For V2 or greater, we
+ // use this to skip to the end of the header
+ int resMgrHeaderVersion = _store.ReadInt32();
+ int numBytesToSkip = _store.ReadInt32();
+ if (numBytesToSkip < 0 || resMgrHeaderVersion < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+ if (resMgrHeaderVersion > 1)
+ {
+ _store.BaseStream.Seek(numBytesToSkip, SeekOrigin.Current);
+ }
+ else
+ {
+ // We don't care about numBytesToSkip; read the rest of the header
+
+ // Read in type name for a suitable ResourceReader
+ // Note ResourceWriter & InternalResGen use different Strings.
+ string readerType = _store.ReadString();
+ readerType = System.CoreLib.FixupCoreLibName(readerType);
+ AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName);
+
+ if (!ResourceManager.CompareNames(readerType, ResourceManager.ResReaderTypeName, mscorlib))
+ throw new NotSupportedException(SR.Format(SR.NotSupported_WrongResourceReader_Type, readerType));
+
+ // Skip over type name for a suitable ResourceSet
+ SkipString();
+ }
+
+ // Read RuntimeResourceSet header
+ // Do file version check
+ int version = _store.ReadInt32();
+ if (version != RuntimeResourceSet.Version && version != 1)
+ throw new ArgumentException(SR.Format(SR.Arg_ResourceFileUnsupportedVersion, RuntimeResourceSet.Version, version));
+ _version = version;
+
+ _numResources = _store.ReadInt32();
+ if (_numResources < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+
+ // Read type positions into type positions array.
+ // But delay initialize the type table.
+ int numTypes = _store.ReadInt32();
+ if (numTypes < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+ _typeTable = new Type[numTypes];
+ _typeNamePositions = new int[numTypes];
+ for (int i = 0; i < numTypes; i++)
+ {
+ _typeNamePositions[i] = (int)_store.BaseStream.Position;
+
+ // Skip over the Strings in the file. Don't create types.
+ SkipString();
+ }
+
+ // Prepare to read in the array of name hashes
+ // Note that the name hashes array is aligned to 8 bytes so
+ // we can use pointers into it on 64 bit machines. (4 bytes
+ // may be sufficient, but let's plan for the future)
+ // Skip over alignment stuff. All public .resources files
+ // should be aligned No need to verify the byte values.
+ long pos = _store.BaseStream.Position;
+ int alignBytes = ((int)pos) & 7;
+ if (alignBytes != 0)
+ {
+ for (int i = 0; i < 8 - alignBytes; i++)
+ {
+ _store.ReadByte();
+ }
+ }
+
+ // Read in the array of name hashes
+ if (_ums == null)
+ {
+ _nameHashes = new int[_numResources];
+ for (int i = 0; i < _numResources; i++)
+ {
+ _nameHashes[i] = _store.ReadInt32();
+ }
+ }
+ else
+ {
+ int seekPos = unchecked(4 * _numResources);
+ if (seekPos < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+ unsafe
+ {
+ _nameHashesPtr = (int*)_ums.PositionPointer;
+ // Skip over the array of nameHashes.
+ _ums.Seek(seekPos, SeekOrigin.Current);
+ // get the position pointer once more to check that the whole table is within the stream
+ byte* junk = _ums.PositionPointer;
+ }
+ }
+
+ // Read in the array of relative positions for all the names.
+ if (_ums == null)
+ {
+ _namePositions = new int[_numResources];
+ for (int i = 0; i < _numResources; i++)
+ {
+ int namePosition = _store.ReadInt32();
+ if (namePosition < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+
+ _namePositions[i] = namePosition;
+ }
+ }
+ else
+ {
+ int seekPos = unchecked(4 * _numResources);
+ if (seekPos < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+ unsafe
+ {
+ _namePositionsPtr = (int*)_ums.PositionPointer;
+ // Skip over the array of namePositions.
+ _ums.Seek(seekPos, SeekOrigin.Current);
+ // get the position pointer once more to check that the whole table is within the stream
+ byte* junk = _ums.PositionPointer;
+ }
+ }
+
+ // Read location of data section.
+ _dataSectionOffset = _store.ReadInt32();
+ if (_dataSectionOffset < 0)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+
+ // Store current location as start of name section
+ _nameSectionOffset = _store.BaseStream.Position;
+
+ // _nameSectionOffset should be <= _dataSectionOffset; if not, it's corrupt
+ if (_dataSectionOffset < _nameSectionOffset)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_ResourcesHeaderCorrupted);
+ }
+ }
+
+ // This allows us to delay-initialize the Type[]. This might be a
+ // good startup time savings, since we might have to load assemblies
+ // and initialize Reflection.
+ private Type FindType(int typeIndex)
+ {
+ if (typeIndex < 0 || typeIndex >= _typeTable.Length)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_InvalidType);
+ }
+ if (_typeTable[typeIndex] == null)
+ {
+ long oldPos = _store.BaseStream.Position;
+ try
+ {
+ _store.BaseStream.Position = _typeNamePositions[typeIndex];
+ string typeName = _store.ReadString();
+ _typeTable[typeIndex] = Type.GetType(typeName, true);
+ }
+ // If serialization isn't supported, we convert FileNotFoundException to
+ // NotSupportedException for consistency with v2. This is a corner-case, but the
+ // idea is that we want to give the user a more accurate error message. Even if
+ // the dependency were found, we know it will require serialization since it
+ // can't be one of the types we special case. So if the dependency were found,
+ // it would go down the serialization code path, resulting in NotSupported for
+ // SKUs without serialization.
+ //
+ // We don't want to regress the expected case by checking the type info before
+ // getting to Type.GetType -- this is costly with v1 resource formats.
+ catch (FileNotFoundException)
+ {
+ throw new NotSupportedException(SR.NotSupported_ResourceObjectSerialization);
+ }
+ finally
+ {
+ _store.BaseStream.Position = oldPos;
+ }
+ }
+ Debug.Assert(_typeTable[typeIndex] != null, "Should have found a type!");
+ return _typeTable[typeIndex];
+ }
+
+ public void GetResourceData(string resourceName, out string resourceType, out byte[] resourceData)
+ {
+ if (resourceName == null)
+ throw new ArgumentNullException(nameof(resourceName));
+ if (_resCache == null)
+ throw new InvalidOperationException(SR.ResourceReaderIsClosed);
+
+ // Get the type information from the data section. Also,
+ // sort all of the data section's indexes to compute length of
+ // the serialized data for this type (making sure to subtract
+ // off the length of the type code).
+ int[] sortedDataPositions = new int[_numResources];
+ int dataPos = FindPosForResource(resourceName);
+ if (dataPos == -1)
+ {
+ throw new ArgumentException(SR.Format(SR.Arg_ResourceNameNotExist, resourceName));
+ }
+
+ lock (this)
+ {
+ // Read all the positions of data within the data section.
+ for (int i = 0; i < _numResources; i++)
+ {
+ _store.BaseStream.Position = _nameSectionOffset + GetNamePosition(i);
+ // Skip over name of resource
+ int numBytesToSkip = _store.Read7BitEncodedInt();
+ if (numBytesToSkip < 0)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesNameInvalidOffset, numBytesToSkip));
+ }
+ _store.BaseStream.Position += numBytesToSkip;
+
+ int dPos = _store.ReadInt32();
+ if (dPos < 0 || dPos >= _store.BaseStream.Length - _dataSectionOffset)
+ {
+ throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesDataInvalidOffset, dPos));
+ }
+ sortedDataPositions[i] = dPos;
+ }
+ Array.Sort(sortedDataPositions);
+
+ int index = Array.BinarySearch(sortedDataPositions, dataPos);
+ Debug.Assert(index >= 0 && index < _numResources, "Couldn't find data position within sorted data positions array!");
+ long nextData = (index < _numResources - 1) ? sortedDataPositions[index + 1] + _dataSectionOffset : _store.BaseStream.Length;
+ int len = (int)(nextData - (dataPos + _dataSectionOffset));
+ Debug.Assert(len >= 0 && len <= (int)_store.BaseStream.Length - dataPos + _dataSectionOffset, "Length was negative or outside the bounds of the file!");
+
+ // Read type code then byte[]
+ _store.BaseStream.Position = _dataSectionOffset + dataPos;
+ ResourceTypeCode typeCode = (ResourceTypeCode)_store.Read7BitEncodedInt();
+ if (typeCode < 0 || typeCode >= ResourceTypeCode.StartOfUserTypes + _typeTable.Length)
+ {
+ throw new BadImageFormatException(SR.BadImageFormat_InvalidType);
+ }
+ resourceType = TypeNameFromTypeCode(typeCode);
+
+ // The length must be adjusted to subtract off the number
+ // of bytes in the 7 bit encoded type code.
+ len -= (int)(_store.BaseStream.Position - (_dataSectionOffset + dataPos));
+ byte[] bytes = _store.ReadBytes(len);
+ if (bytes.Length != len)
+ throw new FormatException(SR.BadImageFormat_ResourceNameCorrupted);
+ resourceData = bytes;
+ }
+ }
+
+ private string TypeNameFromTypeCode(ResourceTypeCode typeCode)
+ {
+ Debug.Assert(typeCode >= 0, "can't be negative");
+ if (typeCode < ResourceTypeCode.StartOfUserTypes)
+ {
+ Debug.Assert(!string.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers.");
+ return "ResourceTypeCode." + typeCode.ToString();
+ }
+ else
+ {
+ int typeIndex = typeCode - ResourceTypeCode.StartOfUserTypes;
+ Debug.Assert(typeIndex >= 0 && typeIndex < _typeTable.Length, "TypeCode is broken or corrupted!");
+ long oldPos = _store.BaseStream.Position;
+ try
+ {
+ _store.BaseStream.Position = _typeNamePositions[typeIndex];
+ return _store.ReadString();
+ }
+ finally
+ {
+ _store.BaseStream.Position = oldPos;
+ }
+ }
+ }
+
+ internal sealed class ResourceEnumerator : IDictionaryEnumerator
+ {
+ private const int ENUM_DONE = int.MinValue;
+ private const int ENUM_NOT_STARTED = -1;
+
+ private ResourceReader _reader;
+ private bool _currentIsValid;
+ private int _currentName;
+ private int _dataPosition; // cached for case-insensitive table
+
+ internal ResourceEnumerator(ResourceReader reader)
+ {
+ _currentName = ENUM_NOT_STARTED;
+ _reader = reader;
+ _dataPosition = -2;
+ }
+
+ public bool MoveNext()
+ {
+ if (_currentName == _reader._numResources - 1 || _currentName == ENUM_DONE)
+ {
+ _currentIsValid = false;
+ _currentName = ENUM_DONE;
+ return false;
+ }
+ _currentIsValid = true;
+ _currentName++;
+ return true;
+ }
+
+ public object Key
+ {
+ get
+ {
+ if (_currentName == ENUM_DONE) throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
+ if (!_currentIsValid) throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed);
+
+ return _reader.AllocateStringForNameIndex(_currentName, out _dataPosition);
+ }
+ }
+
+ public object Current
+ {
+ get
+ {
+ return Entry;
+ }
+ }
+
+ // Warning: This requires that you call the Key or Entry property FIRST before calling it!
+ internal int DataPosition
+ {
+ get
+ {
+ return _dataPosition;
+ }
+ }
+
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ if (_currentName == ENUM_DONE) throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
+ if (!_currentIsValid) throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed);
+
+ string key;
+ object value = null;
+ lock (_reader)
+ { // locks should be taken in the same order as in RuntimeResourceSet.GetObject to avoid deadlock
+ lock (_reader._resCache)
+ {
+ key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // AllocateStringForNameIndex could lock on _reader
+ ResourceLocator locator;
+ if (_reader._resCache.TryGetValue(key, out locator))
+ {
+ value = locator.Value;
+ }
+ if (value == null)
+ {
+ if (_dataPosition == -1)
+ value = _reader.GetValueForNameIndex(_currentName);
+ else
+ value = _reader.LoadObject(_dataPosition);
+ // If enumeration and subsequent lookups happen very
+ // frequently in the same process, add a ResourceLocator
+ // to _resCache here. But WinForms enumerates and
+ // just about everyone else does lookups. So caching
+ // here may bloat working set.
+ }
+ }
+ }
+ return new DictionaryEntry(key, value);
+ }
+ }
+
+ public object Value
+ {
+ get
+ {
+ if (_currentName == ENUM_DONE) throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
+ if (!_currentIsValid) throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed);
+
+ // Consider using _resCache here, eventually, if
+ // this proves to be an interesting perf scenario.
+ // But mixing lookups and enumerators shouldn't be
+ // particularly compelling.
+ return _reader.GetValueForNameIndex(_currentName);
+ }
+ }
+
+ public void Reset()
+ {
+ if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed);
+ _currentIsValid = false;
+ _currentName = ENUM_NOT_STARTED;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs
new file mode 100644
index 000000000..2d33f3a8b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs
@@ -0,0 +1,262 @@
+// 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.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Culture-specific collection of resources.
+**
+**
+===========================================================*/
+
+using System.Collections;
+using System.IO;
+using System.Reflection;
+
+namespace System.Resources
+{
+ // A ResourceSet stores all the resources defined in one particular CultureInfo.
+ //
+ // The method used to load resources is straightforward - this class
+ // enumerates over an IResourceReader, loading every name and value, and
+ // stores them in a hash table. Custom IResourceReaders can be used.
+ //
+ public class ResourceSet : IDisposable, IEnumerable
+ {
+ protected IResourceReader Reader;
+ internal Hashtable Table;
+
+ private Hashtable _caseInsensitiveTable; // For case-insensitive lookups.
+
+ protected ResourceSet()
+ {
+ // To not inconvenience people subclassing us, we should allocate a new
+ // hashtable here just so that Table is set to something.
+ CommonInit();
+ }
+
+ // For RuntimeResourceSet, ignore the Table parameter - it's a wasted
+ // allocation.
+ internal ResourceSet(bool junk)
+ {
+ }
+
+ // Creates a ResourceSet using the system default ResourceReader
+ // implementation. Use this constructor to open & read from a file
+ // on disk.
+ //
+ public ResourceSet(string fileName)
+ {
+ Reader = new ResourceReader(fileName);
+ CommonInit();
+ ReadResources();
+ }
+
+ // Creates a ResourceSet using the system default ResourceReader
+ // implementation. Use this constructor to read from an open stream
+ // of data.
+ //
+ public ResourceSet(Stream stream)
+ {
+ Reader = new ResourceReader(stream);
+ CommonInit();
+ ReadResources();
+ }
+
+ public ResourceSet(IResourceReader reader)
+ {
+ if (reader == null)
+ throw new ArgumentNullException(nameof(reader));
+ Reader = reader;
+ CommonInit();
+ ReadResources();
+ }
+
+ private void CommonInit()
+ {
+ Table = new Hashtable();
+ }
+
+ // Closes and releases any resources used by this ResourceSet, if any.
+ // All calls to methods on the ResourceSet after a call to close may
+ // fail. Close is guaranteed to be safely callable multiple times on a
+ // particular ResourceSet, and all subclasses must support these semantics.
+ public virtual void Close()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // Close the Reader in a thread-safe way.
+ IResourceReader copyOfReader = Reader;
+ Reader = null;
+ if (copyOfReader != null)
+ copyOfReader.Close();
+ }
+ Reader = null;
+ _caseInsensitiveTable = null;
+ Table = null;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ // Returns the preferred IResourceReader class for this kind of ResourceSet.
+ // Subclasses of ResourceSet using their own Readers &; should override
+ // GetDefaultReader and GetDefaultWriter.
+ public virtual Type GetDefaultReader()
+ {
+ return typeof(ResourceReader);
+ }
+
+ // Returns the preferred IResourceWriter class for this kind of ResourceSet.
+ // Subclasses of ResourceSet using their own Readers &; should override
+ // GetDefaultReader and GetDefaultWriter.
+ public virtual Type GetDefaultWriter()
+ {
+ Assembly resourceWriterAssembly = Assembly.Load("System.Resources.Writer, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
+ return resourceWriterAssembly.GetType("System.Resources.ResourceWriter", true);
+ }
+
+ public virtual IDictionaryEnumerator GetEnumerator()
+ {
+ return GetEnumeratorHelper();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumeratorHelper();
+ }
+
+ private IDictionaryEnumerator GetEnumeratorHelper()
+ {
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
+ if (copyOfTable == null)
+ throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
+ return copyOfTable.GetEnumerator();
+ }
+
+ // Look up a string value for a resource given its name.
+ //
+ public virtual string GetString(string name)
+ {
+ object obj = GetObjectInternal(name);
+ try
+ {
+ return (string)obj;
+ }
+ catch (InvalidCastException)
+ {
+ throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Name, name));
+ }
+ }
+
+ public virtual string GetString(string name, bool ignoreCase)
+ {
+ object obj;
+ string s;
+
+ // Case-sensitive lookup
+ obj = GetObjectInternal(name);
+ try
+ {
+ s = (string)obj;
+ }
+ catch (InvalidCastException)
+ {
+ throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Name, name));
+ }
+
+ // case-sensitive lookup succeeded
+ if (s != null || !ignoreCase)
+ {
+ return s;
+ }
+
+ // Try doing a case-insensitive lookup
+ obj = GetCaseInsensitiveObjectInternal(name);
+ try
+ {
+ return (string)obj;
+ }
+ catch (InvalidCastException)
+ {
+ throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Name, name));
+ }
+ }
+
+ // Look up an object value for a resource given its name.
+ //
+ public virtual object GetObject(string name)
+ {
+ return GetObjectInternal(name);
+ }
+
+ public virtual object GetObject(string name, bool ignoreCase)
+ {
+ object obj = GetObjectInternal(name);
+
+ if (obj != null || !ignoreCase)
+ return obj;
+
+ return GetCaseInsensitiveObjectInternal(name);
+ }
+
+ protected virtual void ReadResources()
+ {
+ IDictionaryEnumerator en = Reader.GetEnumerator();
+ while (en.MoveNext())
+ {
+ object value = en.Value;
+ Table.Add(en.Key, value);
+ }
+ // While technically possible to close the Reader here, don't close it
+ // to help with some WinRes lifetime issues.
+ }
+
+ private object GetObjectInternal(string name)
+ {
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
+
+ if (copyOfTable == null)
+ throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
+
+ return copyOfTable[name];
+ }
+
+ private object GetCaseInsensitiveObjectInternal(string name)
+ {
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
+
+ if (copyOfTable == null)
+ throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
+
+ Hashtable caseTable = _caseInsensitiveTable; // Avoid a race condition with Close
+ if (caseTable == null)
+ {
+ caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
+
+ IDictionaryEnumerator en = copyOfTable.GetEnumerator();
+ while (en.MoveNext())
+ {
+ caseTable.Add(en.Key, en.Value);
+ }
+ _caseInsensitiveTable = caseTable;
+ }
+
+ return caseTable[name];
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs b/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs
index a63e68c19..426e17bdb 100644
--- a/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs
@@ -173,7 +173,7 @@ namespace System.Resources
// for arbitrarily long times, since the object is usually a string
// literal that will live for the lifetime of the appdomain. The
// value is a ResourceLocator instance, which might cache the object.
- private Dictionary<String, ResourceLocator> _resCache;
+ private Dictionary<string, ResourceLocator> _resCache;
// For our special load-on-demand reader, cache the cast. The
@@ -185,15 +185,15 @@ namespace System.Resources
// want to fill this out if we can avoid it. The problem is resource
// fallback will somewhat regularly cause us to look up resources that
// don't exist.
- private Dictionary<String, ResourceLocator> _caseInsensitiveTable;
+ private Dictionary<string, ResourceLocator> _caseInsensitiveTable;
// If we're not using our custom reader, then enumerate through all
// the resources once, adding them into the table.
private bool _haveReadFromReader;
- internal RuntimeResourceSet(String fileName) : base(false)
+ internal RuntimeResourceSet(string fileName) : base(false)
{
- _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
_defaultReader = new ResourceReader(stream, _resCache);
Reader = _defaultReader;
@@ -201,7 +201,7 @@ namespace System.Resources
internal RuntimeResourceSet(Stream stream) : base(false)
{
- _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
_defaultReader = new ResourceReader(stream, _resCache);
Reader = _defaultReader;
}
@@ -256,36 +256,36 @@ namespace System.Resources
}
- public override String GetString(String key)
+ public override string GetString(string key)
{
- Object o = GetObject(key, false, true);
- return (String)o;
+ object o = GetObject(key, false, true);
+ return (string)o;
}
- public override String GetString(String key, bool ignoreCase)
+ public override string GetString(string key, bool ignoreCase)
{
- Object o = GetObject(key, ignoreCase, true);
- return (String)o;
+ object o = GetObject(key, ignoreCase, true);
+ return (string)o;
}
- public override Object GetObject(String key)
+ public override object GetObject(string key)
{
return GetObject(key, false, false);
}
- public override Object GetObject(String key, bool ignoreCase)
+ public override object GetObject(string key, bool ignoreCase)
{
return GetObject(key, ignoreCase, false);
}
- private Object GetObject(String key, bool ignoreCase, bool isString)
+ private object GetObject(string key, bool ignoreCase, bool isString)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
if (Reader == null || _resCache == null)
throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- Object value = null;
+ object value = null;
ResourceLocator resLocation;
lock (Reader)
@@ -348,7 +348,7 @@ namespace System.Resources
// If necessary, init our case insensitive hash table.
if (ignoreCase && _caseInsensitiveTable == null)
{
- _caseInsensitiveTable = new Dictionary<String, ResourceLocator>(StringComparer.OrdinalIgnoreCase);
+ _caseInsensitiveTable = new Dictionary<string, ResourceLocator>(StringComparer.OrdinalIgnoreCase);
}
if (_defaultReader == null)
@@ -357,7 +357,7 @@ namespace System.Resources
while (en.MoveNext())
{
DictionaryEntry entry = en.Entry;
- String readKey = (String)entry.Key;
+ string readKey = (string)entry.Key;
ResourceLocator resLoc = new ResourceLocator(-1, entry.Value);
_resCache.Add(readKey, resLoc);
if (ignoreCase)
@@ -375,7 +375,7 @@ namespace System.Resources
while (en.MoveNext())
{
// Note: Always ask for the resource key before the data position.
- String currentKey = (String)en.Key;
+ string currentKey = (string)en.Key;
int dataPos = en.DataPosition;
ResourceLocator resLoc = new ResourceLocator(dataPos, null);
_caseInsensitiveTable.Add(currentKey, resLoc);
@@ -383,7 +383,7 @@ namespace System.Resources
}
_haveReadFromReader = true;
}
- Object obj = null;
+ object obj = null;
bool found = false;
bool keyInWrongCase = false;
if (_defaultReader != null)
@@ -410,11 +410,11 @@ namespace System.Resources
// The last parameter indicates whether the lookup required a
// case-insensitive lookup to succeed, indicating we shouldn't add
// the ResourceLocation to our case-sensitive cache.
- private Object ResolveResourceLocator(ResourceLocator resLocation, String key, Dictionary<String, ResourceLocator> copyOfCache, bool keyInWrongCase)
+ private object ResolveResourceLocator(ResourceLocator resLocation, string key, Dictionary<string, ResourceLocator> copyOfCache, bool keyInWrongCase)
{
// We need to explicitly resolve loosely linked manifest
// resources, and we need to resolve ResourceLocators with null objects.
- Object value = resLocation.Value;
+ object value = resLocation.Value;
if (value == null)
{
ResourceTypeCode typeCode;
diff --git a/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs b/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs
index 070744767..aeccadca9 100644
--- a/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs
@@ -19,13 +19,13 @@ namespace System.Resources
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class SatelliteContractVersionAttribute : Attribute
{
- public SatelliteContractVersionAttribute(String version)
+ public SatelliteContractVersionAttribute(string version)
{
if (version == null)
throw new ArgumentNullException(nameof(version));
Version = version;
}
- public String Version { get; }
+ public string Version { get; }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs
new file mode 100644
index 000000000..6e1c4c56c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs
@@ -0,0 +1,17 @@
+// 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.
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ public sealed class CallerArgumentExpressionAttribute : Attribute
+ {
+ public CallerArgumentExpressionAttribute(string parameterName)
+ {
+ ParameterName = parameterName;
+ }
+
+ public string ParameterName { get; }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
index b6f12299b..8f7b0c809 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
@@ -33,7 +33,7 @@ namespace System.Runtime.CompilerServices
[StructLayout(LayoutKind.Auto)]
public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>The value being awaited.</summary>
@@ -59,55 +59,64 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable"/>.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
ValueTaskSourceOnCompletedFlags.FlowExecutionContext |
- (_value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
+ (_value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
}
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable"/>.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, _value._continueOnCapturedContext);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value._continueOnCapturedContext);
}
}
#endif
@@ -135,7 +144,7 @@ namespace System.Runtime.CompilerServices
[StructLayout(LayoutKind.Auto)]
public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>The value being awaited.</summary>
@@ -161,58 +170,67 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
ValueTaskSourceOnCompletedFlags.FlowExecutionContext |
- (_value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
+ (_value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
}
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, _value._continueOnCapturedContext);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value._continueOnCapturedContext);
}
}
#endif
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
index f75693eb4..d3116cc8a 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
@@ -7,6 +7,6 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
public abstract class CustomConstantAttribute : Attribute
{
- public abstract Object Value { get; }
+ public abstract object Value { get; }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
index 813e6803b..44c497706 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
@@ -14,6 +14,6 @@ namespace System.Runtime.CompilerServices
_date = new DateTime(ticks);
}
- public override Object Value => _date;
+ public override object Value => _date;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
index 19db84eb4..521a3abe9 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
@@ -9,7 +9,7 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
public sealed class DecimalConstantAttribute : Attribute
{
- private Decimal _dec;
+ private decimal _dec;
[CLSCompliant(false)]
public DecimalConstantAttribute(
@@ -20,7 +20,7 @@ namespace System.Runtime.CompilerServices
uint low
)
{
- _dec = new Decimal((int)low, (int)mid, (int)hi, (sign != 0), scale);
+ _dec = new decimal((int)low, (int)mid, (int)hi, (sign != 0), scale);
}
public DecimalConstantAttribute(
@@ -31,9 +31,9 @@ namespace System.Runtime.CompilerServices
int low
)
{
- _dec = new Decimal(low, mid, hi, (sign != 0), scale);
+ _dec = new decimal(low, mid, hi, (sign != 0), scale);
}
- public Decimal Value => _dec;
+ public decimal Value => _dec;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs
index 0fe07edc9..7bb7acec4 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs
@@ -7,13 +7,13 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class DependencyAttribute : Attribute
{
- public DependencyAttribute(String dependentAssemblyArgument, LoadHint loadHintArgument)
+ public DependencyAttribute(string dependentAssemblyArgument, LoadHint loadHintArgument)
{
DependentAssembly = dependentAssemblyArgument;
LoadHint = loadHintArgument;
}
- public String DependentAssembly { get; }
+ public string DependentAssembly { get; }
public LoadHint LoadHint { get; }
}
} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs
new file mode 100644
index 000000000..37e77358a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs
@@ -0,0 +1,61 @@
+// 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;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Support for dynamic interface casting. Specifically implementing this interface on a type will allow the
+ /// type to support interfaces (for the purposes of casting and interface dispatch) that do not appear in its
+ /// interface map.
+ /// </summary>
+ public interface ICastable
+ {
+ // This is called if casting this object to the given interface type would otherwise fail. Casting
+ // here means the IL isinst and castclass instructions in the case where they are given an interface
+ // type as the target type.
+ //
+ // A return value of true indicates the cast is valid.
+ //
+ // If false is returned when this is called as part of a castclass then the usual InvalidCastException
+ // will be thrown unless an alternate exception is assigned to the castError output parameter. This
+ // parameter is ignored on successful casts or during the evaluation of an isinst (which returns null
+ // rather than throwing on error).
+ //
+ // No exception should be thrown from this method (it will cause unpredictable effects, including the
+ // possibility of an immediate failfast).
+ //
+ // The results of this call are not cached, so it is advisable to provide a performant implementation.
+ //
+ // The results of this call should be invariant for the same class, interface type pair. That is
+ // because this is the only guard placed before an interface invocation at runtime. If a type decides
+ // it no longer wants to implement a given interface it has no way to synchronize with callers that
+ // have already cached this relationship and can invoke directly via the interface pointer.
+ bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception castError);
+
+ // This is called as part of the interface dispatch mechanism when the dispatcher logic cannot find
+ // the given interface type in the interface map of this object.
+ //
+ // It allows the implementor to return an alternate class type which does implement the interface. The
+ // interface lookup shall be performed again on this type (failure to find the interface this time
+ // resulting in a fail fast) and the corresponding implemented method on that class called instead.
+ //
+ // Naturally, since the call is dispatched to a method on a class which does not match the type of the
+ // this pointer, extreme care must be taken in the implementation of the interface methods of this
+ // surrogate type.
+ //
+ // No exception should be thrown from this method (it will cause unpredictable effects, including the
+ // possibility of an immediate failfast).
+ //
+ // There is no error path defined here. By construction all interface dispatches will already have
+ // been verified via the castclass/isinst mechanism (and thus a call to IsInstanceOfInterface above)
+ // so this method is expected to succeed in all cases. The contract for interface dispatch does not
+ // include any errors from the infrastructure, of which this is a part.
+ //
+ // The results of this lookup are cached so computation of the result is not as perf-sensitive as
+ // IsInstanceOfInterface.
+ RuntimeTypeHandle GetImplType(RuntimeTypeHandle interfaceType);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs
index ea843b3da..bc76250ad 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs
@@ -7,7 +7,7 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Property, Inherited = true)]
public sealed class IndexerNameAttribute : Attribute
{
- public IndexerNameAttribute(String indexerName)
+ public IndexerNameAttribute(string indexerName)
{
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
index f3842ec56..6c6fe9e25 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
@@ -22,11 +22,11 @@ namespace System.Runtime.CompilerServices
{
}
- public ReferenceAssemblyAttribute(String description)
+ public ReferenceAssemblyAttribute(string description)
{
Description = description;
}
- public String Description { get; }
+ public string Description { get; }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs
new file mode 100644
index 000000000..030278dcf
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs
@@ -0,0 +1,609 @@
+// 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.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Types for awaiting Task and Task<T>. These types are emitted from Task{<T>}.GetAwaiter
+// and Task{<T>}.ConfigureAwait. They are meant to be used only by the compiler, e.g.
+//
+// await nonGenericTask;
+// =====================
+// var $awaiter = nonGenericTask.GetAwaiter();
+// if (!$awaiter.IsCompleted)
+// {
+// SPILL:
+// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this);
+// return;
+// Label:
+// UNSPILL;
+// }
+// $awaiter.GetResult();
+//
+// result += await genericTask.ConfigureAwait(false);
+// ===================================================================================
+// var $awaiter = genericTask.ConfigureAwait(false).GetAwaiter();
+// if (!$awaiter.IsCompleted)
+// {
+// SPILL;
+// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this);
+// return;
+// Label:
+// UNSPILL;
+// }
+// result += $awaiter.GetResult();
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Diagnostics;
+using System.Diagnostics.Tracing;
+using System.Threading;
+using System.Threading.Tasks;
+#if !CORECLR
+using Internal.Threading.Tasks.Tracing;
+#endif
+
+// NOTE: For performance reasons, initialization is not verified. If a developer
+// incorrectly initializes a task awaiter, which should only be done by the compiler,
+// NullReferenceExceptions may be generated (the alternative would be for us to detect
+// this case and then throw a different exception instead). This is the same tradeoff
+// that's made with other compiler-focused value types like List<T>.Enumerator.
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public readonly struct TaskAwaiter : ICriticalNotifyCompletion, ITaskAwaiter
+ {
+ // WARNING: Unsafe.As is used to access the generic TaskAwaiter<> as TaskAwaiter.
+ // Its layout must remain the same.
+
+ /// <summary>The task being awaited.</summary>
+ internal readonly Task m_task;
+
+ /// <summary>Initializes the <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to be awaited.</param>
+ internal TaskAwaiter(Task task)
+ {
+ Debug.Assert(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void OnCompleted(Action continuation)
+ {
+ OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ [StackTraceHidden]
+ public void GetResult()
+ {
+ ValidateEnd(m_task);
+ }
+
+ /// <summary>
+ /// Fast checks for the end of an await operation to determine whether more needs to be done
+ /// prior to completing the await.
+ /// </summary>
+ /// <param name="task">The awaited task.</param>
+ [StackTraceHidden]
+ internal static void ValidateEnd(Task task)
+ {
+ // Fast checks that can be inlined.
+ if (task.IsWaitNotificationEnabledOrNotRanToCompletion)
+ {
+ // If either the end await bit is set or we're not completed successfully,
+ // fall back to the slower path.
+ HandleNonSuccessAndDebuggerNotification(task);
+ }
+ }
+
+ /// <summary>
+ /// Ensures the task is completed, triggers any necessary debugger breakpoints for completing
+ /// the await on the task, and throws an exception if the task did not complete successfully.
+ /// </summary>
+ /// <param name="task">The awaited task.</param>
+ [StackTraceHidden]
+ private static void HandleNonSuccessAndDebuggerNotification(Task task)
+ {
+ // NOTE: The JIT refuses to inline ValidateEnd when it contains the contents
+ // of HandleNonSuccessAndDebuggerNotification, hence the separation.
+
+ // Synchronously wait for the task to complete. When used by the compiler,
+ // the task will already be complete. This code exists only for direct GetResult use,
+ // for cases where the same exception propagation semantics used by "await" are desired,
+ // but where for one reason or another synchronous rather than asynchronous waiting is needed.
+ if (!task.IsCompleted)
+ {
+ bool taskCompleted = task.InternalWait(Timeout.Infinite, default);
+ Debug.Assert(taskCompleted, "With an infinite timeout, the task should have always completed.");
+ }
+
+ // Now that we're done, alert the debugger if so requested
+ task.NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // And throw an exception if the task is faulted or canceled.
+ if (!task.IsCompletedSuccessfully) ThrowForNonSuccess(task);
+ }
+
+ /// <summary>Throws an exception to handle a task that completed in a state other than RanToCompletion.</summary>
+ [StackTraceHidden]
+ private static void ThrowForNonSuccess(Task task)
+ {
+ Debug.Assert(task.IsCompleted, "Task must have been completed by now.");
+ Debug.Assert(task.Status != TaskStatus.RanToCompletion, "Task should not be completed successfully.");
+
+ // Handle whether the task has been canceled or faulted
+ switch (task.Status)
+ {
+ // If the task completed in a canceled state, throw an OperationCanceledException.
+ // This will either be the OCE that actually caused the task to cancel, or it will be a new
+ // TaskCanceledException. TCE derives from OCE, and by throwing it we automatically pick up the
+ // completed task's CancellationToken if it has one, including that CT in the OCE.
+ case TaskStatus.Canceled:
+ var oceEdi = task.GetCancellationExceptionDispatchInfo();
+ if (oceEdi != null)
+ {
+ oceEdi.Throw();
+ Debug.Fail("Throw() should have thrown");
+ }
+ throw new TaskCanceledException(task);
+
+ // If the task faulted, throw its first exception,
+ // even if it contained more than one.
+ case TaskStatus.Faulted:
+ var edis = task.GetExceptionDispatchInfos();
+ if (edis.Count > 0)
+ {
+ edis[0].Throw();
+ Debug.Fail("Throw() should have thrown");
+ break; // Necessary to compile: non-reachable, but compiler can't determine that
+ }
+ else
+ {
+ Debug.Fail("There should be exceptions if we're Faulted.");
+ throw task.Exception;
+ }
+ }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="task">The task being awaited.</param>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+ /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext, bool flowExecutionContext)
+ {
+ if (continuation == null) throw new ArgumentNullException(nameof(continuation));
+
+ // If TaskWait* ETW events are enabled, trace a beginning event for this await
+ // and set up an ending event to be traced when the asynchronous await completes.
+ if (
+#if CORECLR
+ TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled
+#else
+ TaskTrace.Enabled
+#endif
+ )
+ {
+ continuation = OutputWaitEtwEvents(task, continuation);
+ }
+
+ // Set the continuation onto the awaited task.
+ task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext);
+ }
+
+#if CORECLR
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="task">The task being awaited.</param>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+ /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ internal static void UnsafeOnCompletedInternal(Task task, IAsyncStateMachineBox stateMachineBox, bool continueOnCapturedContext)
+ {
+ Debug.Assert(stateMachineBox != null);
+
+ // If TaskWait* ETW events are enabled, trace a beginning event for this await
+ // and set up an ending event to be traced when the asynchronous await completes.
+ if (TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled)
+ {
+ task.SetContinuationForAwait(OutputWaitEtwEvents(task, stateMachineBox.MoveNextAction), continueOnCapturedContext, flowExecutionContext: false);
+ }
+ else
+ {
+ task.UnsafeSetContinuationForAwait(stateMachineBox, continueOnCapturedContext);
+ }
+ }
+#endif
+ /// <summary>
+ /// Outputs a WaitBegin ETW event, and augments the continuation action to output a WaitEnd ETW event.
+ /// </summary>
+ /// <param name="task">The task being awaited.</param>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <returns>The action to use as the actual continuation.</returns>
+ private static Action OutputWaitEtwEvents(Task task, Action continuation)
+ {
+ Debug.Assert(task != null, "Need a task to wait on");
+ Debug.Assert(continuation != null, "Need a continuation to invoke when the wait completes");
+#if CORECLR
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(task);
+ }
+
+ var etwLog = TplEtwProvider.Log;
+
+ if (etwLog.IsEnabled())
+ {
+ // ETW event for Task Wait Begin
+ var currentTaskAtBegin = Task.InternalCurrent;
+
+ // If this task's continuation is another task, get it.
+ var continuationTask = AsyncMethodBuilderCore.TryGetContinuationTask(continuation);
+ etwLog.TaskWaitBegin(
+ (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0),
+ task.Id, TplEtwProvider.TaskWaitBehavior.Asynchronous,
+ (continuationTask != null ? continuationTask.Id : 0));
+ }
+#else
+ Debug.Assert(TaskTrace.Enabled, "Should only be used when ETW tracing is enabled");
+
+ // ETW event for Task Wait Begin
+ var currentTaskAtBegin = Task.InternalCurrent;
+ TaskTrace.TaskWaitBegin_Asynchronous(
+ (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0),
+ task.Id);
+#endif
+
+ // Create a continuation action that outputs the end event and then invokes the user
+ // provided delegate. This incurs the allocations for the closure/delegate, but only if the event
+ // is enabled, and in doing so it allows us to pass the awaited task's information into the end event
+ // in a purely pay-for-play manner (the alternatively would be to increase the size of TaskAwaiter
+ // just for this ETW purpose, not pay-for-play, since GetResult would need to know whether a real yield occurred).
+#if CORECLR
+ return AsyncMethodBuilderCore.CreateContinuationWrapper(continuation, (innerContinuation,innerTask) =>
+ {
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(innerTask.Id);
+ }
+
+ TplEtwProvider innerEtwLog = TplEtwProvider.Log;
+
+ // ETW event for Task Wait End.
+ Guid prevActivityId = new Guid();
+ bool bEtwLogEnabled = innerEtwLog.IsEnabled();
+ if (bEtwLogEnabled)
+ {
+ var currentTaskAtEnd = Task.InternalCurrent;
+ innerEtwLog.TaskWaitEnd(
+ (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtEnd != null ? currentTaskAtEnd.Id : 0),
+ innerTask.Id);
+
+ // Ensure the continuation runs under the activity ID of the task that completed for the
+ // case the antecedent is a promise (in the other cases this is already the case).
+ if (innerEtwLog.TasksSetActivityIds && (innerTask.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(innerTask.Id), out prevActivityId);
+ }
+
+ // Invoke the original continuation provided to OnCompleted.
+ innerContinuation();
+
+ if (bEtwLogEnabled)
+ {
+ innerEtwLog.TaskWaitContinuationComplete(innerTask.Id);
+ if (innerEtwLog.TasksSetActivityIds && (innerTask.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ EventSource.SetCurrentThreadActivityId(prevActivityId);
+ }
+ }, task);
+#else
+ return () =>
+ {
+ // ETW event for Task Wait End.
+ if (TaskTrace.Enabled)
+ {
+ var currentTaskAtEnd = Task.InternalCurrent;
+ TaskTrace.TaskWaitEnd(
+ (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtEnd != null ? currentTaskAtEnd.Id : 0),
+ task.Id);
+ }
+
+ // Invoke the original continuation provided to OnCompleted.
+ continuation();
+ };
+#endif
+ }
+ }
+
+ /// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public readonly struct TaskAwaiter<TResult> : ICriticalNotifyCompletion, ITaskAwaiter
+ {
+ // WARNING: Unsafe.As is used to access TaskAwaiter<> as the non-generic TaskAwaiter.
+ // Its layout must remain the same.
+
+ /// <summary>The task being awaited.</summary>
+ private readonly Task<TResult> m_task;
+
+ /// <summary>Initializes the <see cref="TaskAwaiter{TResult}"/>.</summary>
+ /// <param name="task">The <see cref="System.Threading.Tasks.Task{TResult}"/> to be awaited.</param>
+ internal TaskAwaiter(Task<TResult> task)
+ {
+ Debug.Assert(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ [StackTraceHidden]
+ public TResult GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ return m_task.ResultOnSuccess;
+ }
+ }
+
+ /// <summary>
+ /// Marker interface used to know whether a particular awaiter is either a
+ /// TaskAwaiter or a TaskAwaiter`1. It must not be implemented by any other
+ /// awaiters.
+ /// </summary>
+ internal interface ITaskAwaiter { }
+
+ /// <summary>
+ /// Marker interface used to know whether a particular awaiter is either a
+ /// CTA.ConfiguredTaskAwaiter or a CTA`1.ConfiguredTaskAwaiter. It must not
+ /// be implemented by any other awaiters.
+ /// </summary>
+ internal interface IConfiguredTaskAwaiter { }
+
+ /// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public readonly struct ConfiguredTaskAwaitable
+ {
+ /// <summary>The task being awaited.</summary>
+ private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaitable"/>.</summary>
+ /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext)
+ {
+ Debug.Assert(task != null, "Constructing an awaitable requires a task to await.");
+ m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext);
+ }
+
+ /// <summary>Gets an awaiter for this awaitable.</summary>
+ /// <returns>The awaiter.</returns>
+ public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter()
+ {
+ return m_configuredTaskAwaiter;
+ }
+
+ /// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public readonly struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion, IConfiguredTaskAwaiter
+ {
+ // WARNING: Unsafe.As is used to access the generic ConfiguredTaskAwaiter as this.
+ // Its layout must remain the same.
+
+ /// <summary>The task being awaited.</summary>
+ internal readonly Task m_task;
+ /// <summary>Whether to attempt marshaling back to the original context.</summary>
+ internal readonly bool m_continueOnCapturedContext;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary>
+ /// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to await.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured
+ /// when BeginAwait is called; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext)
+ {
+ Debug.Assert(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ m_continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ [StackTraceHidden]
+ public void GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ }
+ }
+ }
+
+ /// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public readonly struct ConfiguredTaskAwaitable<TResult>
+ {
+ /// <summary>The underlying awaitable on whose logic this awaitable relies.</summary>
+ private readonly ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter m_configuredTaskAwaiter;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary>
+ /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaitable(Task<TResult> task, bool continueOnCapturedContext)
+ {
+ m_configuredTaskAwaiter = new ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter(task, continueOnCapturedContext);
+ }
+
+ /// <summary>Gets an awaiter for this awaitable.</summary>
+ /// <returns>The awaiter.</returns>
+ public ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter GetAwaiter()
+ {
+ return m_configuredTaskAwaiter;
+ }
+
+ /// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public readonly struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion, IConfiguredTaskAwaiter
+ {
+ // WARNING: Unsafe.As is used to access this as the non-generic ConfiguredTaskAwaiter.
+ // Its layout must remain the same.
+
+ /// <summary>The task being awaited.</summary>
+ private readonly Task<TResult> m_task;
+ /// <summary>Whether to attempt marshaling back to the original context.</summary>
+ private readonly bool m_continueOnCapturedContext;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary>
+ /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaiter(Task<TResult> task, bool continueOnCapturedContext)
+ {
+ Debug.Assert(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ m_continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ [StackTraceHidden]
+ public TResult GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ return m_task.ResultOnSuccess;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
index 221a1a437..02b5910b7 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
@@ -6,12 +6,16 @@ using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
+#if !netstandard
+using Internal.Runtime.CompilerServices;
+#endif
+
namespace System.Runtime.CompilerServices
{
/// <summary>Provides an awaiter for a <see cref="ValueTask"/>.</summary>
public readonly struct ValueTaskAwaiter : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>Shim used to invoke an <see cref="Action"/> passed as the state argument to a <see cref="Action{Object}"/>.</summary>
@@ -48,13 +52,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().GetAwaiter().OnCompleted(continuation);
+ t.GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
}
else
{
@@ -65,13 +72,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().GetAwaiter().UnsafeOnCompleted(continuation);
+ t.GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -80,15 +90,18 @@ namespace System.Runtime.CompilerServices
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, continueOnCapturedContext: true);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, continueOnCapturedContext: true);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -105,7 +118,7 @@ namespace System.Runtime.CompilerServices
return;
}
- box.Invoke(null);
+ box.MoveNext();
};
#endif
}
@@ -113,7 +126,7 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary>
public readonly struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>The value being awaited.</summary>
@@ -139,13 +152,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().GetAwaiter().OnCompleted(continuation);
+ t.GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
}
else
{
@@ -156,13 +172,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().GetAwaiter().UnsafeOnCompleted(continuation);
+ t.GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -171,15 +190,18 @@ namespace System.Runtime.CompilerServices
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, continueOnCapturedContext: true);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, continueOnCapturedContext: true);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -190,12 +212,12 @@ namespace System.Runtime.CompilerServices
}
#if CORECLR
- /// <summary>Internal interface used to enable optimizations from <see cref="AsyncTaskMethodBuilder"/> on <see cref="ValueTask"/>.</summary>>
- internal interface IValueTaskAwaiter
+ /// <summary>Internal interface used to enable optimizations from <see cref="AsyncTaskMethodBuilder"/>.</summary>>
+ internal interface IStateMachineBoxAwareAwaiter
{
/// <summary>Invoked to set <see cref="ITaskCompletionAction.Invoke"/> of the <paramref name="box"/> as the awaiter's continuation.</summary>
/// <param name="box">The box object.</param>
void AwaitUnsafeOnCompleted(IAsyncStateMachineBox box);
}
#endif
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs
index c45ef2484..68fd5ab8d 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs
@@ -47,6 +47,9 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter that switches into a target environment.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
public readonly struct YieldAwaiter : ICriticalNotifyCompletion
+#if CORECLR
+ , IStateMachineBoxAwareAwaiter
+#endif
{
/// <summary>Gets whether a yield is not required.</summary>
/// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
@@ -110,11 +113,46 @@ namespace System.Runtime.CompilerServices
// We're targeting a custom scheduler, so queue a task.
else
{
- Task.Factory.StartNew(continuation, default(CancellationToken), TaskCreationOptions.PreferFairness, scheduler);
+ Task.Factory.StartNew(continuation, default, TaskCreationOptions.PreferFairness, scheduler);
}
}
}
+#if CORECLR
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ {
+ Debug.Assert(box != null);
+
+ // If tracing is enabled, delegate the Action-based implementation.
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ QueueContinuation(box.MoveNextAction, flowContext: false);
+ return;
+ }
+
+ // Otherwise, this is the same logic as in QueueContinuation, except using
+ // an IAsyncStateMachineBox instead of an Action, and only for flowContext:false.
+
+ SynchronizationContext syncCtx = SynchronizationContext.Current;
+ if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
+ {
+ syncCtx.Post(s => ((IAsyncStateMachineBox)s).MoveNext(), box);
+ }
+ else
+ {
+ TaskScheduler scheduler = TaskScheduler.Current;
+ if (scheduler == TaskScheduler.Default)
+ {
+ ThreadPool.UnsafeQueueUserWorkItem(s => ((IAsyncStateMachineBox)s).MoveNext(), box);
+ }
+ else
+ {
+ Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler);
+ }
+ }
+ }
+#endif
+
private static Action OutputCorrelationEtwEvent(Action continuation)
{
#if CORERT
@@ -153,7 +191,6 @@ namespace System.Runtime.CompilerServices
private static readonly WaitCallback s_waitCallbackRunAction = RunAction;
/// <summary>SendOrPostCallback that invokes the Action supplied as object state.</summary>
private static readonly SendOrPostCallback s_sendOrPostCallbackRunAction = RunAction;
-
/// <summary>Runs an Action delegate provided as state.</summary>
/// <param name="state">The Action delegate to invoke.</param>
private static void RunAction(object state) { ((Action)state)(); }
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs
new file mode 100644
index 000000000..3f35f816a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs
@@ -0,0 +1,28 @@
+// 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.
+
+/*============================================================
+**
+**
+** Deriving from this class will cause any finalizer you define to be critical
+** (i.e. the finalizer is guaranteed to run, won't be aborted by the host and is
+** run after the finalizers of other objects collected at the same time).
+**
+**
+===========================================================*/
+
+namespace System.Runtime.ConstrainedExecution
+{
+ public abstract class CriticalFinalizerObject
+ {
+ protected CriticalFinalizerObject()
+ {
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1821:RemoveEmptyFinalizers")]
+ ~CriticalFinalizerObject()
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
index 160fe301e..ab5a84c08 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
@@ -68,7 +68,7 @@ namespace System.Runtime.InteropServices
string s = className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")";
- if (!(String.IsNullOrEmpty(message)))
+ if (!(string.IsNullOrEmpty(message)))
{
s = s + ": " + message;
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs
index 64d055313..c81a70199 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs
@@ -4,12 +4,12 @@
namespace System.Runtime.InteropServices
{
- public struct HandleRef
+ public readonly struct HandleRef
{
// ! Do not add or rearrange fields as the EE depends on this layout.
//------------------------------------------------------------------
- private object _wrapper;
- private IntPtr _handle;
+ private readonly object _wrapper;
+ private readonly IntPtr _handle;
//------------------------------------------------------------------
public HandleRef(object wrapper, IntPtr handle)
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs
index 1d0d59fab..3bb1140f5 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs
@@ -27,13 +27,13 @@ namespace System.Runtime.InteropServices
HResult = HResults.COR_E_MARSHALDIRECTIVE;
}
- public MarshalDirectiveException(String message)
+ public MarshalDirectiveException(string message)
: base(message)
{
HResult = HResults.COR_E_MARSHALDIRECTIVE;
}
- public MarshalDirectiveException(String message, Exception inner)
+ public MarshalDirectiveException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MARSHALDIRECTIVE;
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
index 8a5bb7539..e3cf0a84e 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
@@ -2,9 +2,7 @@
// 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.Buffers;
using System.Runtime.CompilerServices;
-using System.Collections.Generic;
using Internal.Runtime.CompilerServices;
namespace System.Runtime.InteropServices
@@ -15,8 +13,54 @@ namespace System.Runtime.InteropServices
/// </summary>
public static partial class MemoryMarshal
{
+ /// <summary>
+ /// Casts a Span of one primitive type <typeparamref name="T"/> to Span of bytes.
+ /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <param name="span">The source slice, of type <typeparamref name="T"/>.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when <typeparamref name="T"/> contains pointers.
+ /// </exception>
+ /// <exception cref="System.OverflowException">
+ /// Thrown if the Length property of the new Span would exceed int.MaxValue.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<byte> AsBytes<T>(Span<T> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+
+ return new Span<byte>(
+ ref Unsafe.As<T, byte>(ref GetReference(span)),
+ checked(span.Length * Unsafe.SizeOf<T>()));
+ }
+
+ /// <summary>
+ /// Casts a ReadOnlySpan of one primitive type <typeparamref name="T"/> to ReadOnlySpan of bytes.
+ /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <param name="span">The source slice, of type <typeparamref name="T"/>.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when <typeparamref name="T"/> contains pointers.
+ /// </exception>
+ /// <exception cref="System.OverflowException">
+ /// Thrown if the Length property of the new Span would exceed int.MaxValue.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<byte> AsBytes<T>(ReadOnlySpan<T> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+
+ return new ReadOnlySpan<byte>(
+ ref Unsafe.As<T, byte>(ref GetReference(span)),
+ checked(span.Length * Unsafe.SizeOf<T>()));
+ }
+
/// <summary>Creates a <see cref="Memory{T}"/> from a <see cref="ReadOnlyMemory{T}"/>.</summary>
- /// <param name="readOnlyMemory">The <see cref="ReadOnlyMemory{T}"/>.</param>
+ /// <param name="memory">The <see cref="ReadOnlyMemory{T}"/>.</param>
/// <returns>A <see cref="Memory{T}"/> representing the same memory as the <see cref="ReadOnlyMemory{T}"/>, but writable.</returns>
/// <remarks>
/// <see cref="AsMemory{T}(ReadOnlyMemory{T})"/> must be used with extreme caution. <see cref="ReadOnlyMemory{T}"/> is used
@@ -24,33 +68,48 @@ namespace System.Runtime.InteropServices
/// by <see cref="AsMemory{T}(ReadOnlyMemory{T})"/> should not be written to. The method exists to enable variables typed
/// as <see cref="Memory{T}"/> but only used for reading to store a <see cref="ReadOnlyMemory{T}"/>.
/// </remarks>
- public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> readOnlyMemory) =>
- Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref readOnlyMemory);
+ public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> memory) =>
+ Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref memory);
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
- /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
+ /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
/// </summary>
public static ref T GetReference<T>(Span<T> span) => ref span._pointer.Value;
/// <summary>
- /// Returns a reference to the 0th element of the ReadOnlySpan. If the Span is empty, returns a reference to the location where the 0th element
- /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
+ /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to the location where the 0th element
+ /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
/// </summary>
public static ref T GetReference<T>(ReadOnlySpan<T> span) => ref span._pointer.Value;
/// <summary>
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to fake non-null pointer. Such a reference can be used
+ /// for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static unsafe ref T GetNonNullPinnableReference<T>(Span<T> span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef<T>((void*)1);
+
+ /// <summary>
+ /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to fake non-null pointer. Such a reference
+ /// can be used for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static unsafe ref T GetNonNullPinnableReference<T>(ReadOnlySpan<T> span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef<T>((void*)1);
+
+ /// <summary>
/// Casts a Span of one primitive type <typeparamref name="TFrom"/> to another primitive type <typeparamref name="TTo"/>.
/// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
- /// Supported only for platforms that support misaligned memory access.
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
/// </remarks>
- /// <param name="source">The source slice, of type <typeparamref name="TFrom"/>.</param>
+ /// <param name="span">The source slice, of type <typeparamref name="TFrom"/>.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
- public static Span<TTo> Cast<TFrom, TTo>(Span<TFrom> source)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<TTo> Cast<TFrom, TTo>(Span<TFrom> span)
where TFrom : struct
where TTo : struct
{
@@ -63,7 +122,7 @@ namespace System.Runtime.InteropServices
// and checked casts are faster and smaller.
uint fromSize = (uint)Unsafe.SizeOf<TFrom>();
uint toSize = (uint)Unsafe.SizeOf<TTo>();
- uint fromLength = (uint)source.Length;
+ uint fromLength = (uint)span.Length;
int toLength;
if (fromSize == toSize)
{
@@ -89,7 +148,7 @@ namespace System.Runtime.InteropServices
}
return new Span<TTo>(
- ref Unsafe.As<TFrom, TTo>(ref source._pointer.Value),
+ ref Unsafe.As<TFrom, TTo>(ref span._pointer.Value),
toLength);
}
@@ -98,13 +157,14 @@ namespace System.Runtime.InteropServices
/// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
- /// Supported only for platforms that support misaligned memory access.
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
/// </remarks>
- /// <param name="source">The source slice, of type <typeparamref name="TFrom"/>.</param>
+ /// <param name="span">The source slice, of type <typeparamref name="TFrom"/>.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
- public static ReadOnlySpan<TTo> Cast<TFrom, TTo>(ReadOnlySpan<TFrom> source)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<TTo> Cast<TFrom, TTo>(ReadOnlySpan<TFrom> span)
where TFrom : struct
where TTo : struct
{
@@ -117,7 +177,7 @@ namespace System.Runtime.InteropServices
// and checked casts are faster and smaller.
uint fromSize = (uint)Unsafe.SizeOf<TFrom>();
uint toSize = (uint)Unsafe.SizeOf<TTo>();
- uint fromLength = (uint)source.Length;
+ uint fromLength = (uint)span.Length;
int toLength;
if (fromSize == toSize)
{
@@ -143,7 +203,7 @@ namespace System.Runtime.InteropServices
}
return new ReadOnlySpan<TTo>(
- ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(source)),
+ ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(span)),
toLength);
}
@@ -154,6 +214,7 @@ namespace System.Runtime.InteropServices
/// </summary>
/// <param name="reference">A reference to data.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
+ /// <returns>The lifetime of the returned span will not be validated for safety by span-aware languages.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> CreateSpan<T>(ref T reference, int length) => new Span<T>(ref reference, length);
@@ -164,6 +225,7 @@ namespace System.Runtime.InteropServices
/// </summary>
/// <param name="reference">A reference to data.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
+ /// <returns>The lifetime of the returned span will not be validated for safety by span-aware languages.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
index 316ce12aa..fcc9c4f41 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
@@ -5,6 +5,9 @@
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
+using System.Diagnostics;
+
+using Internal.Runtime.CompilerServices;
namespace System.Runtime.InteropServices
{
@@ -18,72 +21,78 @@ namespace System.Runtime.InteropServices
/// Get an array segment from the underlying memory.
/// If unable to get the array segment, return false with a default array segment.
/// </summary>
- public static bool TryGetArray<T>(ReadOnlyMemory<T> readOnlyMemory, out ArraySegment<T> arraySegment)
+ public static bool TryGetArray<T>(ReadOnlyMemory<T> memory, out ArraySegment<T> segment)
{
- object obj = readOnlyMemory.GetObjectStartLength(out int index, out int length);
+ object obj = memory.GetObjectStartLength(out int index, out int length);
if (index < 0)
{
- if (((OwnedMemory<T>)obj).TryGetArray(out var segment))
+ Debug.Assert(length >= 0);
+ if (((MemoryManager<T>)obj).TryGetArray(out ArraySegment<T> arraySegment))
{
- arraySegment = new ArraySegment<T>(segment.Array, segment.Offset + (index & ReadOnlyMemory<T>.RemoveOwnedFlagBitMask), length);
+ segment = new ArraySegment<T>(arraySegment.Array, arraySegment.Offset + (index & ReadOnlyMemory<T>.RemoveFlagsBitMask), length);
return true;
}
}
else if (obj is T[] arr)
{
- arraySegment = new ArraySegment<T>(arr, index, length);
+ segment = new ArraySegment<T>(arr, index, length & ReadOnlyMemory<T>.RemoveFlagsBitMask);
return true;
}
- if (length == 0)
+ if ((length & ReadOnlyMemory<T>.RemoveFlagsBitMask) == 0)
{
-#if FEATURE_PORTABLE_SPAN
- arraySegment = new ArraySegment<T>(SpanHelpers.PerTypeValues<T>.EmptyArray);
-#else
- arraySegment = ArraySegment<T>.Empty;
-#endif // FEATURE_PORTABLE_SPAN
+ segment = ArraySegment<T>.Empty;
return true;
}
- arraySegment = default;
+ segment = default;
return false;
}
/// <summary>
- /// Gets an <see cref="OwnedMemory{T}"/> from the underlying readOnlyMemory.
- /// If unable to get the <typeparamref name="TOwner"/> type, returns false.
+ /// Gets an <see cref="MemoryManager{T}"/> from the underlying read-only memory.
+ /// If unable to get the <typeparamref name="TManager"/> type, returns false.
/// </summary>
- /// <typeparam name="T">The element type of the <paramref name="readOnlyMemory" />.</typeparam>
- /// <typeparam name="TOwner">The type of <see cref="OwnedMemory{T}"/> to try and retrive.</typeparam>
- /// <param name="readOnlyMemory">The memory to get the owner for.</param>
- /// <param name="ownedMemory">The returned owner of the <see cref="ReadOnlyMemory{T}"/>.</param>
+ /// <typeparam name="T">The element type of the <paramref name="memory" />.</typeparam>
+ /// <typeparam name="TManager">The type of <see cref="MemoryManager{T}"/> to try and retrive.</typeparam>
+ /// <param name="memory">The memory to get the manager for.</param>
+ /// <param name="manager">The returned manager of the <see cref="ReadOnlyMemory{T}"/>.</param>
/// <returns>A <see cref="bool"/> indicating if it was successful.</returns>
- public static bool TryGetOwnedMemory<T, TOwner>(ReadOnlyMemory<T> readOnlyMemory, out TOwner ownedMemory)
- where TOwner : OwnedMemory<T>
+ public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager manager)
+ where TManager : MemoryManager<T>
{
- TOwner owner; // Use register for null comparison rather than byref
- ownedMemory = owner = readOnlyMemory.GetObjectStartLength(out int index, out int length) as TOwner;
- return !ReferenceEquals(owner, null);
+ TManager localManager; // Use register for null comparison rather than byref
+ manager = localManager = memory.GetObjectStartLength(out _, out _) as TManager;
+ return manager != null;
}
/// <summary>
- /// Gets an <see cref="OwnedMemory{T}"/> and <paramref name="index" />, <paramref name="length" /> from the underlying memory.
- /// If unable to get the <typeparamref name="TOwner"/> type, returns false.
+ /// Gets an <see cref="MemoryManager{T}"/> and <paramref name="start" />, <paramref name="length" /> from the underlying read-only memory.
+ /// If unable to get the <typeparamref name="TManager"/> type, returns false.
/// </summary>
- /// <typeparam name="T">The element type of the <paramref name="readOnlyMemory" />.</typeparam>
- /// <typeparam name="TOwner">The type of <see cref="OwnedMemory{T}"/> to try and retrive.</typeparam>
- /// <param name="readOnlyMemory">The memory to get the owner for.</param>
- /// <param name="ownedMemory">The returned owner of the <see cref="ReadOnlyMemory{T}"/>.</param>
- /// <param name="index">The offset from the start of the <paramref name="ownedMemory" /> that the <paramref name="readOnlyMemory" /> represents.</param>
- /// <param name="length">The length of the <paramref name="ownedMemory" /> that the <paramref name="readOnlyMemory" /> represents.</param>
+ /// <typeparam name="T">The element type of the <paramref name="memory" />.</typeparam>
+ /// <typeparam name="TManager">The type of <see cref="MemoryManager{T}"/> to try and retrive.</typeparam>
+ /// <param name="memory">The memory to get the manager for.</param>
+ /// <param name="manager">The returned manager of the <see cref="ReadOnlyMemory{T}"/>.</param>
+ /// <param name="start">The offset from the start of the <paramref name="manager" /> that the <paramref name="memory" /> represents.</param>
+ /// <param name="length">The length of the <paramref name="manager" /> that the <paramref name="memory" /> represents.</param>
/// <returns>A <see cref="bool"/> indicating if it was successful.</returns>
- public static bool TryGetOwnedMemory<T, TOwner>(ReadOnlyMemory<T> readOnlyMemory, out TOwner ownedMemory, out int index, out int length)
- where TOwner : OwnedMemory<T>
+ public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager manager, out int start, out int length)
+ where TManager : MemoryManager<T>
{
- TOwner owner; // Use register for null comparison rather than byref
- ownedMemory = owner = readOnlyMemory.GetObjectStartLength(out index, out length) as TOwner;
- index &= ReadOnlyMemory<T>.RemoveOwnedFlagBitMask;
- return !ReferenceEquals(owner, null);
+ TManager localManager; // Use register for null comparison rather than byref
+ manager = localManager = memory.GetObjectStartLength(out start, out length) as TManager;
+ start &= ReadOnlyMemory<T>.RemoveFlagsBitMask;
+
+ Debug.Assert(length >= 0);
+
+ if (manager == null)
+ {
+ start = default;
+ length = default;
+ return false;
+ }
+ return true;
}
/// <summary>
@@ -100,15 +109,17 @@ namespace System.Runtime.InteropServices
}
/// <summary>Attempts to get the underlying <see cref="string"/> from a <see cref="ReadOnlyMemory{T}"/>.</summary>
- /// <param name="readOnlyMemory">The memory that may be wrapping a <see cref="string"/> object.</param>
+ /// <param name="memory">The memory that may be wrapping a <see cref="string"/> object.</param>
/// <param name="text">The string.</param>
/// <param name="start">The starting location in <paramref name="text"/>.</param>
/// <param name="length">The number of items in <paramref name="text"/>.</param>
/// <returns></returns>
- public static bool TryGetString(ReadOnlyMemory<char> readOnlyMemory, out string text, out int start, out int length)
+ public static bool TryGetString(ReadOnlyMemory<char> memory, out string text, out int start, out int length)
{
- if (readOnlyMemory.GetObjectStartLength(out int offset, out int count) is string s)
+ if (memory.GetObjectStartLength(out int offset, out int count) is string s)
{
+ Debug.Assert(offset >= 0);
+ Debug.Assert(count >= 0);
text = s;
start = offset;
length = count;
@@ -122,5 +133,159 @@ namespace System.Runtime.InteropServices
return false;
}
}
+
+ /// <summary>
+ /// Reads a structure of type T out of a read-only span of bytes.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T Read<T>(ReadOnlySpan<byte> source)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > source.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return Unsafe.ReadUnaligned<T>(ref GetReference(source));
+ }
+
+ /// <summary>
+ /// Reads a structure of type T out of a span of bytes.
+ /// <returns>If the span is too small to contain the type T, return false.</returns>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool TryRead<T>(ReadOnlySpan<byte> source, out T value)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)source.Length)
+ {
+ value = default;
+ return false;
+ }
+ value = Unsafe.ReadUnaligned<T>(ref GetReference(source));
+ return true;
+ }
+
+ /// <summary>
+ /// Writes a structure of type T into a span of bytes.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Write<T>(Span<byte> destination, ref T value)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if ((uint)Unsafe.SizeOf<T>() > (uint)destination.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ Unsafe.WriteUnaligned<T>(ref GetReference(destination), value);
+ }
+
+ /// <summary>
+ /// Writes a structure of type T into a span of bytes.
+ /// <returns>If the span is too small to contain the type T, return false.</returns>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool TryWrite<T>(Span<byte> destination, ref T value)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)destination.Length)
+ {
+ return false;
+ }
+ Unsafe.WriteUnaligned<T>(ref GetReference(destination), value);
+ return true;
+ }
+
+ /// <summary>
+ /// Re-interprets a span of bytes as a reference to structure of type T.
+ /// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <remarks>
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
+ /// </remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AsRef<T>(Span<byte> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)span.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return ref Unsafe.As<byte, T>(ref GetReference(span));
+ }
+
+ /// <summary>
+ /// Re-interprets a span of bytes as a reference to structure of type T.
+ /// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <remarks>
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
+ /// </remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref readonly T AsRef<T>(ReadOnlySpan<byte> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)span.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return ref Unsafe.As<byte, T>(ref GetReference(span));
+ }
+
+ /// <summary>
+ /// Creates a new memory over the portion of the pre-pinned target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="array">The pre-pinned target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <remarks>This method should only be called on an array that is already pinned and
+ /// that array should not be unpinned while the returned Memory<typeparamref name="T"/> is still in use.
+ /// Calling this method on an unpinned array could result in memory corruption.</remarks>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Memory<T> CreateFromPinnedArray<T>(T[] array, int start, int length)
+ {
+ if (array == null)
+ {
+ if (start != 0 || length != 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+ return default;
+ }
+ if (default(T) == null && array.GetType() != typeof(T[]))
+ ThrowHelper.ThrowArrayTypeMismatchException();
+ if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ // Before using _length, check if _length < 0, then 'and' it with RemoveFlagsBitMask
+ return new Memory<T>((object)array, start, length | (1 << 31));
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs
new file mode 100644
index 000000000..bad4d7f6a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs
@@ -0,0 +1,29 @@
+// 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.
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Any method marked with NativeCallableAttribute can be directly called from
+ /// native code. The function token can be loaded to a local variable using LDFTN
+ /// and passed as a callback to native method.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class NativeCallableAttribute : Attribute
+ {
+ public NativeCallableAttribute()
+ {
+ }
+
+ /// <summary>
+ /// Optional. If omitted, compiler will choose one for you.
+ /// </summary>
+ public CallingConvention CallingConvention;
+
+ /// <summary>
+ /// Optional. If omitted, then the method is native callable, but no EAT is emitted.
+ /// </summary>
+ public string EntryPoint;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs
index 455e41392..661a7edce 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs
@@ -77,7 +77,7 @@ namespace System.Runtime.InteropServices
{
// Steal UIntPtr.MaxValue as our uninitialized value.
private static readonly UIntPtr Uninitialized = (UIntPtr.Size == 4) ?
- ((UIntPtr)UInt32.MaxValue) : ((UIntPtr)UInt64.MaxValue);
+ ((UIntPtr)uint.MaxValue) : ((UIntPtr)ulong.MaxValue);
private UIntPtr _numBytes;
@@ -94,7 +94,7 @@ namespace System.Runtime.InteropServices
[CLSCompliant(false)]
public void Initialize(ulong numBytes)
{
- if (IntPtr.Size == 4 && numBytes > UInt32.MaxValue)
+ if (IntPtr.Size == 4 && numBytes > uint.MaxValue)
throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_AddressSpace);
if (numBytes >= (ulong)Uninitialized)
@@ -110,7 +110,7 @@ namespace System.Runtime.InteropServices
[CLSCompliant(false)]
public void Initialize(uint numElements, uint sizeOfEachElement)
{
- if (IntPtr.Size == 4 && numElements * sizeOfEachElement > UInt32.MaxValue)
+ if (IntPtr.Size == 4 && numElements * sizeOfEachElement > uint.MaxValue)
throw new ArgumentOutOfRangeException("numBytes", SR.ArgumentOutOfRange_AddressSpace);
if (numElements * sizeOfEachElement >= (ulong)Uninitialized)
@@ -198,7 +198,7 @@ namespace System.Runtime.InteropServices
SpaceCheck(ptr, sizeofT);
// return *(T*) (_ptr + byteOffset);
- T value = default(T);
+ T value = default;
bool mustCallRelease = false;
try
{
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
new file mode 100644
index 000000000..0ad9634d1
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
@@ -0,0 +1,40 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AES Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.AES is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Aes
+ {
+ public static bool IsSupported { get { return false; } }
+ // <summary>
+ /// Performs AES single round decryption
+ /// vaesdq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs AES single round encryption
+ /// vaeseq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs AES Mix Columns
+ /// vaesmcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> MixColumns(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs AES inverse mix columns
+ /// vaesimcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs
new file mode 100644
index 000000000..24c9342d9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs
@@ -0,0 +1,40 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AES Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.AES is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Aes
+ {
+ public static bool IsSupported { get => IsSupported; }
+ // <summary>
+ /// Performs AES single round decryption
+ /// vaesdq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) => Decrypt(value, roundKey);
+
+ // <summary>
+ /// Performs AES single round encryption
+ /// vaeseq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) => Encrypt(value, roundKey);
+
+ // <summary>
+ /// Performs AES Mix Columns
+ /// vaesmcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> MixColumns(Vector128<byte> value) => MixColumns(value);
+
+ // <summary>
+ /// Performs AES inverse mix columns
+ /// vaesimcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) => InverseMixColumns(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
new file mode 100644
index 000000000..0a13828ee
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
@@ -0,0 +1,33 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 Base intrinsics
+ ///
+ /// These intrinsics are supported by all Arm64 CPUs
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Base
+ {
+ public static bool IsSupported { get { return false; }}
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to integer forms of ARM64 CLS
+ /// </summary>
+ public static int LeadingSignCount(int value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingSignCount(long value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to integer forms of ARM64 CLZ
+ /// </summary>
+ public static int LeadingZeroCount(int value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingZeroCount(uint value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingZeroCount(long value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingZeroCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs
new file mode 100644
index 000000000..fc0a19055
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs
@@ -0,0 +1,33 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 Base intrinsics
+ ///
+ /// These intrinsics are supported by all Arm64 CPUs
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Base
+ {
+ public static bool IsSupported { get { return false; }}
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to integer forms of ARM64 CLS
+ /// </summary>
+ public static int LeadingSignCount(int value) => LeadingSignCount(value);
+ public static int LeadingSignCount(long value) => LeadingSignCount(value);
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to integer forms of ARM64 CLZ
+ /// </summary>
+ public static int LeadingZeroCount(int value) => LeadingZeroCount(value);
+ public static int LeadingZeroCount(uint value) => LeadingZeroCount(value);
+ public static int LeadingZeroCount(long value) => LeadingZeroCount(value);
+ public static int LeadingZeroCount(ulong value) => LeadingZeroCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
new file mode 100644
index 000000000..9b6c5aac6
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
@@ -0,0 +1,54 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA1 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA1 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha1
+ {
+
+ public static bool IsSupported { get { return false; } }
+
+ // <summary>
+ /// Performs SHA1 hash update choose form.
+ /// vsha1cq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashChoose(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 hash update majority form.
+ /// vsha1mq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashMajority(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 hash update parity form.
+ /// vsha1pq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashParity(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 fixed rotate
+ /// vsha1h_u32 (uint32_t hash_e)
+ ///</summary>
+ public static uint FixedRotate(uint hash_e) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 schedule update 0
+ /// vsha1su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7, uint32x4_t w8_11)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7, Vector128<uint> w8_11) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 schedule update 1
+ /// vsha1su1q_u32 (uint32x4_t tw0_3, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> tw0_3, Vector128<uint> w12_15) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs
new file mode 100644
index 000000000..28cc397ce
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs
@@ -0,0 +1,53 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA1 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA1 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha1
+ {
+ public static bool IsSupported { get => IsSupported; }
+
+ // <summary>
+ /// Performs SHA1 hash update choose form.
+ /// vsha1cq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashChoose(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) => HashChoose(hash_abcd, hash_e, wk);
+
+ // <summary>
+ /// Performs SHA1 hash update majority form.
+ /// vsha1mq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashMajority(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) => HashMajority(hash_abcd, hash_e, wk);
+
+ // <summary>
+ /// Performs SHA1 hash update parity form.
+ /// vsha1pq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashParity(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) => HashParity(hash_abcd, hash_e, wk);
+
+ // <summary>
+ /// Performs SHA1 fixed rotate
+ /// vsha1h_u32 (uint32_t hash_e)
+ ///</summary>
+ public static uint FixedRotate(uint hash_e) => FixedRotate(hash_e);
+
+ // <summary>
+ /// Performs SHA1 schedule update 0
+ /// vsha1su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7, uint32x4_t w8_11)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7, Vector128<uint> w8_11) => SchedulePart1(w0_3, w4_7, w8_11);
+
+ // <summary>
+ /// Performs SHA1 schedule update 1
+ /// vsha1su1q_u32 (uint32x4_t tw0_3, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> tw0_3, Vector128<uint> w12_15) => SchedulePart2(tw0_3, w12_15);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
new file mode 100644
index 000000000..052a1d236
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
@@ -0,0 +1,41 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA256 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA2 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha256
+ {
+ public static bool IsSupported { get { return false; } }
+
+ // <summary>
+ /// Performs SHA256 hash update (part 1).
+ /// vsha256hq_u32 (uint32x4_t hash_abcd, uint32x4_t hash_efgh, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashLower(Vector128<uint> hash_abcd, Vector128<uint> hash_efgh, Vector128<uint> wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA256 hash update (part 2).
+ /// vsha256h2q_u32 (uint32x4_t hash_efgh, uint32x4_t hash_abcd, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashUpper(Vector128<uint> hash_efgh, Vector128<uint> hash_abcd, Vector128<uint> wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA256 schedule update 0
+ /// vsha256su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA256 schedule update 1
+ /// vsha256su1q_u32 (uint32x4_t w0_3, uint32x4_t w8_11, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> w0_3, Vector128<uint> w8_11, Vector128<uint> w12_15) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs
new file mode 100644
index 000000000..4e7e51db3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs
@@ -0,0 +1,41 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA256 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA2 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha256
+ {
+ public static bool IsSupported { get => IsSupported; }
+
+ // <summary>
+ /// Performs SHA256 hash update (part 1).
+ /// vsha256hq_u32 (uint32x4_t hash_abcd, uint32x4_t hash_efgh, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashLower(Vector128<uint> hash_abcd, Vector128<uint> hash_efgh, Vector128<uint> wk) => HashLower(hash_abcd, hash_efgh, wk);
+
+ // <summary>
+ /// Performs SHA256 hash update (part 2).
+ /// vsha256h2q_u32 (uint32x4_t hash_efgh, uint32x4_t hash_abcd, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashUpper(Vector128<uint> hash_efgh, Vector128<uint> hash_abcd, Vector128<uint> wk) => HashUpper(hash_efgh, hash_abcd, wk);
+
+ // <summary>
+ /// Performs SHA256 schedule update 0
+ /// vsha256su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7) => SchedulePart1(w0_3, w4_7);
+
+ // <summary>
+ /// Performs SHA256 schedule update 1
+ /// vsha256su1q_u32 (uint32x4_t tw0_3, uint32x4_t w8_11, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> w0_3, Vector128<uint> w8_11, Vector128<uint> w12_15) => SchedulePart2(w0_3, w8_11, w12_15);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
new file mode 100644
index 000000000..4b377902c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
@@ -0,0 +1,344 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AdvSIMD intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64PFR0_EL1.AdvSIMD == 0 or better.
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Simd
+ {
+ /// <summary>
+ /// IsSupported property indicates whether any method provided
+ /// by this class is supported by the current runtime.
+ /// </summary>
+ public static bool IsSupported { get { return false; }}
+
+ /// <summary>
+ /// Vector abs
+ /// Corresponds to vector forms of ARM64 ABS & FABS
+ /// </summary>
+ public static Vector64<byte> Abs(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Abs(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Abs(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Abs(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Abs(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Abs(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Abs(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ulong> Abs(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Abs(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Abs(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector add
+ /// Corresponds to vector forms of ARM64 ADD & FADD
+ /// </summary>
+ public static Vector64<T> Add<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Add<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector and
+ /// Corresponds to vector forms of ARM64 AND
+ /// </summary>
+ public static Vector64<T> And<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> And<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector and not
+ /// Corresponds to vector forms of ARM64 BIC
+ /// </summary>
+ public static Vector64<T> AndNot<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> AndNot<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector BitwiseSelect
+ /// For each bit in the vector result[bit] = sel[bit] ? left[bit] : right[bit]
+ /// Corresponds to vector forms of ARM64 BSL (Also BIF & BIT)
+ /// </summary>
+ public static Vector64<T> BitwiseSelect<T>(Vector64<T> sel, Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> BitwiseSelect<T>(Vector128<T> sel, Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareEqual
+ /// For each element result[elem] = (left[elem] == right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareEqualZero
+ /// For each element result[elem] = (left[elem] == 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqualZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareEqualZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThan
+ /// For each element result[elem] = (left[elem] > right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT/CMHI & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThan<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThan<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThanZero
+ /// For each element result[elem] = (left[elem] > 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThanZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqual
+ /// For each element result[elem] = (left[elem] >= right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE/CMHS & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThanOrEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqualZero
+ /// For each element result[elem] = (left[elem] >= 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqualZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThanOrEqualZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareLessThanZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareLessThanZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareLessThanOrEqualZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanOrEqualZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareLessThanOrEqualZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareTest
+ /// For each element result[elem] = (left[elem] & right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMTST
+ /// </summary>
+ public static Vector64<T> CompareTest<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareTest<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// TBD Convert...
+
+ /// <summary>
+ /// Vector Divide
+ /// Corresponds to vector forms of ARM64 FDIV
+ /// </summary>
+ public static Vector64<float> Divide(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector extract item
+ ///
+ /// result = vector[index]
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 MOV
+ /// </summary>
+ public static T Extract<T>(Vector64<T> vector, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+ public static T Extract<T>(Vector128<T> vector, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector insert item
+ ///
+ /// result = vector;
+ /// result[index] = data;
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 INS
+ /// </summary>
+ public static Vector64<T> Insert<T>(Vector64<T> vector, byte index, T data) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Insert<T>(Vector128<T> vector, byte index, T data) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to vector forms of ARM64 CLS
+ /// </summary>
+ public static Vector64<sbyte> LeadingSignCount(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> LeadingSignCount(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> LeadingSignCount(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> LeadingSignCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> LeadingSignCount(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> LeadingSignCount(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to vector forms of ARM64 CLZ
+ /// </summary>
+ public static Vector64<byte> LeadingZeroCount(Vector64<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> LeadingZeroCount(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> LeadingZeroCount(Vector64<ushort> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> LeadingZeroCount(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> LeadingZeroCount(Vector64<uint> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> LeadingZeroCount(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> LeadingZeroCount(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> LeadingZeroCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> LeadingZeroCount(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> LeadingZeroCount(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> LeadingZeroCount(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> LeadingZeroCount(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector max
+ /// Corresponds to vector forms of ARM64 SMAX, UMAX & FMAX
+ /// </summary>
+ public static Vector64<byte> Max(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> Max(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Max(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Max(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Max(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Max(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Max(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector min
+ /// Corresponds to vector forms of ARM64 SMIN, UMIN & FMIN
+ /// </summary>
+ public static Vector64<byte> Min(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> Min(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Min(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Min(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Min(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Min(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Min(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// TBD MOV, FMOV
+
+ /// <summary>
+ /// Vector multiply
+ ///
+ /// For each element result[elem] = left[elem] * right[elem]
+ ///
+ /// Corresponds to vector forms of ARM64 MUL & FMUL
+ /// </summary>
+ public static Vector64<byte> Multiply(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> Multiply(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Multiply(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Multiply(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Multiply(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Multiply(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Multiply(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Multiply(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Multiply(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Multiply(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Multiply(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Multiply(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Multiply(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector negate
+ /// Corresponds to vector forms of ARM64 NEG & FNEG
+ /// </summary>
+ public static Vector64<sbyte> Negate(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Negate(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Negate(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Negate(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Negate(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Negate(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Negate(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<long> Negate(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Negate(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Negate(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector not
+ /// Corresponds to vector forms of ARM64 NOT
+ /// </summary>
+ public static Vector64<T> Not<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Not<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector or
+ /// Corresponds to vector forms of ARM64 ORR
+ /// </summary>
+ public static Vector64<T> Or<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Or<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector or not
+ /// Corresponds to vector forms of ARM64 ORN
+ /// </summary>
+ public static Vector64<T> OrNot<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> OrNot<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector PopCount
+ /// Corresponds to vector forms of ARM64 CNT
+ /// </summary>
+ public static Vector64<byte> PopCount(Vector64<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> PopCount(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> PopCount(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> PopCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// SetVector* Fill vector elements by replicating element value
+ ///
+ /// Corresponds to vector forms of ARM64 DUP (general), DUP (element 0), FMOV (vector, immediate)
+ /// </summary>
+ public static Vector64<T> SetAllVector64<T>(T value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> SetAllVector128<T>(T value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector square root
+ /// Corresponds to vector forms of ARM64 FRSQRT
+ /// </summary>
+ public static Vector64<float> Sqrt(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Sqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Sqrt(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector subtract
+ /// Corresponds to vector forms of ARM64 SUB & FSUB
+ /// </summary>
+ public static Vector64<T> Subtract<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Subtract<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+
+ /// <summary>
+ /// Vector exclusive or
+ /// Corresponds to vector forms of ARM64 EOR
+ /// </summary>
+ public static Vector64<T> Xor<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Xor<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs
new file mode 100644
index 000000000..f162483da
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs
@@ -0,0 +1,344 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AdvSIMD intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64PFR0_EL1.AdvSIMD == 0 or better.
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Simd
+ {
+ /// <summary>
+ /// IsSupported property indicates whether any method provided
+ /// by this class is supported by the current runtime.
+ /// </summary>
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// Vector abs
+ /// Corresponds to vector forms of ARM64 ABS & FABS
+ /// </summary>
+ public static Vector64<byte> Abs(Vector64<sbyte> value) => Abs(value);
+ public static Vector64<ushort> Abs(Vector64<short> value) => Abs(value);
+ public static Vector64<uint> Abs(Vector64<int> value) => Abs(value);
+ public static Vector64<float> Abs(Vector64<float> value) => Abs(value);
+ public static Vector128<byte> Abs(Vector128<sbyte> value) => Abs(value);
+ public static Vector128<ushort> Abs(Vector128<short> value) => Abs(value);
+ public static Vector128<uint> Abs(Vector128<int> value) => Abs(value);
+ public static Vector128<ulong> Abs(Vector128<long> value) => Abs(value);
+ public static Vector128<float> Abs(Vector128<float> value) => Abs(value);
+ public static Vector128<double> Abs(Vector128<double> value) => Abs(value);
+
+ /// <summary>
+ /// Vector add
+ /// Corresponds to vector forms of ARM64 ADD & FADD
+ /// </summary>
+ public static Vector64<T> Add<T>(Vector64<T> left, Vector64<T> right) where T : struct => Add(left, right);
+ public static Vector128<T> Add<T>(Vector128<T> left, Vector128<T> right) where T : struct => Add(left, right);
+
+ /// <summary>
+ /// Vector and
+ /// Corresponds to vector forms of ARM64 AND
+ /// </summary>
+ public static Vector64<T> And<T>(Vector64<T> left, Vector64<T> right) where T : struct => And(left, right);
+ public static Vector128<T> And<T>(Vector128<T> left, Vector128<T> right) where T : struct => And(left, right);
+
+ /// <summary>
+ /// Vector and not
+ /// Corresponds to vector forms of ARM64 BIC
+ /// </summary>
+ public static Vector64<T> AndNot<T>(Vector64<T> left, Vector64<T> right) where T : struct => AndNot(left, right);
+ public static Vector128<T> AndNot<T>(Vector128<T> left, Vector128<T> right) where T : struct => AndNot(left, right);
+
+ /// <summary>
+ /// Vector BitwiseSelect
+ /// For each bit in the vector result[bit] = sel[bit] ? left[bit] : right[bit]
+ /// Corresponds to vector forms of ARM64 BSL (Also BIF & BIT)
+ /// </summary>
+ public static Vector64<T> BitwiseSelect<T>(Vector64<T> sel, Vector64<T> left, Vector64<T> right) where T : struct => BitwiseSelect(sel, left, right);
+ public static Vector128<T> BitwiseSelect<T>(Vector128<T> sel, Vector128<T> left, Vector128<T> right) where T : struct => BitwiseSelect(sel, left, right);
+
+ /// <summary>
+ /// Vector CompareEqual
+ /// For each element result[elem] = (left[elem] == right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareEqual(left, right);
+ public static Vector128<T> CompareEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareEqual(left, right);
+
+ /// <summary>
+ /// Vector CompareEqualZero
+ /// For each element result[elem] = (left[elem] == 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqualZero<T>(Vector64<T> value) where T : struct => CompareEqualZero(value);
+ public static Vector128<T> CompareEqualZero<T>(Vector128<T> value) where T : struct => CompareEqualZero(value);
+
+ /// <summary>
+ /// Vector CompareGreaterThan
+ /// For each element result[elem] = (left[elem] > right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT/CMHI & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThan<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareGreaterThan(left, right);
+ public static Vector128<T> CompareGreaterThan<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// Vector CompareGreaterThanZero
+ /// For each element result[elem] = (left[elem] > 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanZero<T>(Vector64<T> value) where T : struct => CompareGreaterThanZero(value);
+ public static Vector128<T> CompareGreaterThanZero<T>(Vector128<T> value) where T : struct => CompareGreaterThanZero(value);
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqual
+ /// For each element result[elem] = (left[elem] >= right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE/CMHS & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareGreaterThanOrEqual(left, right);
+ public static Vector128<T> CompareGreaterThanOrEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqualZero
+ /// For each element result[elem] = (left[elem] >= 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqualZero<T>(Vector64<T> value) where T : struct => CompareGreaterThanOrEqualZero(value);
+ public static Vector128<T> CompareGreaterThanOrEqualZero<T>(Vector128<T> value) where T : struct => CompareGreaterThanOrEqualZero(value);
+
+ /// <summary>
+ /// Vector CompareLessThanZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanZero<T>(Vector64<T> value) where T : struct => CompareLessThanZero(value);
+ public static Vector128<T> CompareLessThanZero<T>(Vector128<T> value) where T : struct => CompareLessThanZero(value);
+
+ /// <summary>
+ /// Vector CompareLessThanOrEqualZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanOrEqualZero<T>(Vector64<T> value) where T : struct => CompareLessThanOrEqualZero(value);
+ public static Vector128<T> CompareLessThanOrEqualZero<T>(Vector128<T> value) where T : struct => CompareLessThanOrEqualZero(value);
+
+ /// <summary>
+ /// Vector CompareTest
+ /// For each element result[elem] = (left[elem] & right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMTST
+ /// </summary>
+ public static Vector64<T> CompareTest<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareTest(left, right);
+ public static Vector128<T> CompareTest<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareTest(left, right);
+
+ /// TBD Convert...
+
+ /// <summary>
+ /// Vector Divide
+ /// Corresponds to vector forms of ARM64 FDIV
+ /// </summary>
+ public static Vector64<float> Divide(Vector64<float> left, Vector64<float> right) => Divide(left, right);
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) => Divide(left, right);
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// Vector extract item
+ ///
+ /// result = vector[index]
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 MOV
+ /// </summary>
+ public static T Extract<T>(Vector64<T> vector, byte index) where T : struct => Extract(vector, index);
+ public static T Extract<T>(Vector128<T> vector, byte index) where T : struct => Extract(vector, index);
+
+ /// <summary>
+ /// Vector insert item
+ ///
+ /// result = vector;
+ /// result[index] = data;
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 INS
+ /// </summary>
+ public static Vector64<T> Insert<T>(Vector64<T> vector, byte index, T data) where T : struct => Insert(vector, index, data);
+ public static Vector128<T> Insert<T>(Vector128<T> vector, byte index, T data) where T : struct => Insert(vector, index, data);
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to vector forms of ARM64 CLS
+ /// </summary>
+ public static Vector64<sbyte> LeadingSignCount(Vector64<sbyte> value) => LeadingSignCount(value);
+ public static Vector64<short> LeadingSignCount(Vector64<short> value) => LeadingSignCount(value);
+ public static Vector64<int> LeadingSignCount(Vector64<int> value) => LeadingSignCount(value);
+ public static Vector128<sbyte> LeadingSignCount(Vector128<sbyte> value) => LeadingSignCount(value);
+ public static Vector128<short> LeadingSignCount(Vector128<short> value) => LeadingSignCount(value);
+ public static Vector128<int> LeadingSignCount(Vector128<int> value) => LeadingSignCount(value);
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to vector forms of ARM64 CLZ
+ /// </summary>
+ public static Vector64<byte> LeadingZeroCount(Vector64<byte> value) => LeadingZeroCount(value);
+ public static Vector64<sbyte> LeadingZeroCount(Vector64<sbyte> value) => LeadingZeroCount(value);
+ public static Vector64<ushort> LeadingZeroCount(Vector64<ushort> value) => LeadingZeroCount(value);
+ public static Vector64<short> LeadingZeroCount(Vector64<short> value) => LeadingZeroCount(value);
+ public static Vector64<uint> LeadingZeroCount(Vector64<uint> value) => LeadingZeroCount(value);
+ public static Vector64<int> LeadingZeroCount(Vector64<int> value) => LeadingZeroCount(value);
+ public static Vector128<byte> LeadingZeroCount(Vector128<byte> value) => LeadingZeroCount(value);
+ public static Vector128<sbyte> LeadingZeroCount(Vector128<sbyte> value) => LeadingZeroCount(value);
+ public static Vector128<ushort> LeadingZeroCount(Vector128<ushort> value) => LeadingZeroCount(value);
+ public static Vector128<short> LeadingZeroCount(Vector128<short> value) => LeadingZeroCount(value);
+ public static Vector128<uint> LeadingZeroCount(Vector128<uint> value) => LeadingZeroCount(value);
+ public static Vector128<int> LeadingZeroCount(Vector128<int> value) => LeadingZeroCount(value);
+
+ /// <summary>
+ /// Vector max
+ /// Corresponds to vector forms of ARM64 SMAX, UMAX & FMAX
+ /// </summary>
+ public static Vector64<byte> Max(Vector64<byte> left, Vector64<byte> right) => Max(left, right);
+ public static Vector64<sbyte> Max(Vector64<sbyte> left, Vector64<sbyte> right) => Max(left, right);
+ public static Vector64<ushort> Max(Vector64<ushort> left, Vector64<ushort> right) => Max(left, right);
+ public static Vector64<short> Max(Vector64<short> left, Vector64<short> right) => Max(left, right);
+ public static Vector64<uint> Max(Vector64<uint> left, Vector64<uint> right) => Max(left, right);
+ public static Vector64<int> Max(Vector64<int> left, Vector64<int> right) => Max(left, right);
+ public static Vector64<float> Max(Vector64<float> left, Vector64<float> right) => Max(left, right);
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) => Max(left, right);
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) => Max(left, right);
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) => Max(left, right);
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) => Max(left, right);
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) => Max(left, right);
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) => Max(left, right);
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) => Max(left, right);
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) => Max(left, right);
+
+ /// <summary>
+ /// Vector min
+ /// Corresponds to vector forms of ARM64 SMIN, UMIN & FMIN
+ /// </summary>
+ public static Vector64<byte> Min(Vector64<byte> left, Vector64<byte> right) => Min(left, right);
+ public static Vector64<sbyte> Min(Vector64<sbyte> left, Vector64<sbyte> right) => Min(left, right);
+ public static Vector64<ushort> Min(Vector64<ushort> left, Vector64<ushort> right) => Min(left, right);
+ public static Vector64<short> Min(Vector64<short> left, Vector64<short> right) => Min(left, right);
+ public static Vector64<uint> Min(Vector64<uint> left, Vector64<uint> right) => Min(left, right);
+ public static Vector64<int> Min(Vector64<int> left, Vector64<int> right) => Min(left, right);
+ public static Vector64<float> Min(Vector64<float> left, Vector64<float> right) => Min(left, right);
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) => Min(left, right);
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) => Min(left, right);
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) => Min(left, right);
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) => Min(left, right);
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) => Min(left, right);
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) => Min(left, right);
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) => Min(left, right);
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) => Min(left, right);
+
+ /// TBD MOV, FMOV
+
+ /// <summary>
+ /// Vector multiply
+ ///
+ /// For each element result[elem] = left[elem] * right[elem]
+ ///
+ /// Corresponds to vector forms of ARM64 MUL & FMUL
+ /// </summary>
+ public static Vector64<byte> Multiply(Vector64<byte> left, Vector64<byte> right) => Multiply(left, right);
+ public static Vector64<sbyte> Multiply(Vector64<sbyte> left, Vector64<sbyte> right) => Multiply(left, right);
+ public static Vector64<ushort> Multiply(Vector64<ushort> left, Vector64<ushort> right) => Multiply(left, right);
+ public static Vector64<short> Multiply(Vector64<short> left, Vector64<short> right) => Multiply(left, right);
+ public static Vector64<uint> Multiply(Vector64<uint> left, Vector64<uint> right) => Multiply(left, right);
+ public static Vector64<int> Multiply(Vector64<int> left, Vector64<int> right) => Multiply(left, right);
+ public static Vector64<float> Multiply(Vector64<float> left, Vector64<float> right) => Multiply(left, right);
+ public static Vector128<byte> Multiply(Vector128<byte> left, Vector128<byte> right) => Multiply(left, right);
+ public static Vector128<sbyte> Multiply(Vector128<sbyte> left, Vector128<sbyte> right) => Multiply(left, right);
+ public static Vector128<ushort> Multiply(Vector128<ushort> left, Vector128<ushort> right) => Multiply(left, right);
+ public static Vector128<short> Multiply(Vector128<short> left, Vector128<short> right) => Multiply(left, right);
+ public static Vector128<uint> Multiply(Vector128<uint> left, Vector128<uint> right) => Multiply(left, right);
+ public static Vector128<int> Multiply(Vector128<int> left, Vector128<int> right) => Multiply(left, right);
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) => Multiply(left, right);
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// Vector negate
+ /// Corresponds to vector forms of ARM64 NEG & FNEG
+ /// </summary>
+ public static Vector64<sbyte> Negate(Vector64<sbyte> value) => Negate(value);
+ public static Vector64<short> Negate(Vector64<short> value) => Negate(value);
+ public static Vector64<int> Negate(Vector64<int> value) => Negate(value);
+ public static Vector64<float> Negate(Vector64<float> value) => Negate(value);
+ public static Vector128<sbyte> Negate(Vector128<sbyte> value) => Negate(value);
+ public static Vector128<short> Negate(Vector128<short> value) => Negate(value);
+ public static Vector128<int> Negate(Vector128<int> value) => Negate(value);
+ public static Vector128<long> Negate(Vector128<long> value) => Negate(value);
+ public static Vector128<float> Negate(Vector128<float> value) => Negate(value);
+ public static Vector128<double> Negate(Vector128<double> value) => Negate(value);
+
+ /// <summary>
+ /// Vector not
+ /// Corresponds to vector forms of ARM64 NOT
+ /// </summary>
+ public static Vector64<T> Not<T>(Vector64<T> value) where T : struct => Not(value);
+ public static Vector128<T> Not<T>(Vector128<T> value) where T : struct => Not(value);
+
+ /// <summary>
+ /// Vector or
+ /// Corresponds to vector forms of ARM64 ORR
+ /// </summary>
+ public static Vector64<T> Or<T>(Vector64<T> left, Vector64<T> right) where T : struct => Or(left, right);
+ public static Vector128<T> Or<T>(Vector128<T> left, Vector128<T> right) where T : struct => Or(left, right);
+
+ /// <summary>
+ /// Vector or not
+ /// Corresponds to vector forms of ARM64 ORN
+ /// </summary>
+ public static Vector64<T> OrNot<T>(Vector64<T> left, Vector64<T> right) where T : struct => OrNot(left, right);
+ public static Vector128<T> OrNot<T>(Vector128<T> left, Vector128<T> right) where T : struct => OrNot(left, right);
+
+ /// <summary>
+ /// Vector PopCount
+ /// Corresponds to vector forms of ARM64 CNT
+ /// </summary>
+ public static Vector64<byte> PopCount(Vector64<byte> value) => PopCount(value);
+ public static Vector64<sbyte> PopCount(Vector64<sbyte> value) => PopCount(value);
+ public static Vector128<byte> PopCount(Vector128<byte> value) => PopCount(value);
+ public static Vector128<sbyte> PopCount(Vector128<sbyte> value) => PopCount(value);
+
+ /// <summary>
+ /// SetVector* Fill vector elements by replicating element value
+ ///
+ /// Corresponds to vector forms of ARM64 DUP (general), DUP (element 0), FMOV (vector, immediate)
+ /// </summary>
+ public static Vector64<T> SetAllVector64<T>(T value) where T : struct => SetAllVector64(value);
+ public static Vector128<T> SetAllVector128<T>(T value) where T : struct => SetAllVector128(value);
+
+ /// <summary>
+ /// Vector square root
+ /// Corresponds to vector forms of ARM64 FRSQRT
+ /// </summary>
+ public static Vector64<float> Sqrt(Vector64<float> value) => Sqrt(value);
+ public static Vector128<float> Sqrt(Vector128<float> value) => Sqrt(value);
+ public static Vector128<double> Sqrt(Vector128<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// Vector subtract
+ /// Corresponds to vector forms of ARM64 SUB & FSUB
+ /// </summary>
+ public static Vector64<T> Subtract<T>(Vector64<T> left, Vector64<T> right) where T : struct => Subtract(left, right);
+ public static Vector128<T> Subtract<T>(Vector128<T> left, Vector128<T> right) where T : struct => Subtract(left, right);
+
+
+ /// <summary>
+ /// Vector exclusive or
+ /// Corresponds to vector forms of ARM64 EOR
+ /// </summary>
+ public static Vector64<T> Xor<T>(Vector64<T> left, Vector64<T> right) where T : struct => Xor(left, right);
+ public static Vector128<T> Xor<T>(Vector128<T> left, Vector128<T> right) where T : struct => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs
new file mode 100644
index 000000000..b2e72ddf8
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs
@@ -0,0 +1,44 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ [Intrinsic]
+ [DebuggerDisplay("{DisplayString,nq}")]
+ [DebuggerTypeProxy(typeof(Vector128DebugView<>))]
+ [StructLayout(LayoutKind.Sequential, Size = 16)]
+ public readonly struct Vector128<T> where T : struct
+ {
+ // These fields exist to ensure the alignment is 8, rather than 1.
+ // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
+ private readonly ulong _00;
+ private readonly ulong _01;
+
+ private unsafe string DisplayString
+ {
+ get
+ {
+ // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr`
+ // which are not actually supported by any current architecture. This shouldn't be
+ // an issue however and greatly simplifies the check
+
+ if (typeof(T).IsPrimitive)
+ {
+ var items = new T[16 / Unsafe.SizeOf<T>()];
+ Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref items[0]), this);
+ return $"({string.Join(", ", items)})";
+ }
+ else
+ {
+ return SR.NotSupported_Type;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs
new file mode 100644
index 000000000..ccdc65594
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs
@@ -0,0 +1,118 @@
+// 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 Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ internal readonly struct Vector128DebugView<T> where T : struct
+ {
+ private readonly Vector128<T> _value;
+
+ public Vector128DebugView(Vector128<T> value)
+ {
+ _value = value;
+ }
+
+ public byte[] ByteView
+ {
+ get
+ {
+ var items = new byte[16];
+ Unsafe.WriteUnaligned(ref items[0], _value);
+ return items;
+ }
+ }
+
+ public double[] DoubleView
+ {
+ get
+ {
+ var items = new double[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<double, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public short[] Int16View
+ {
+ get
+ {
+ var items = new short[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<short, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public int[] Int32View
+ {
+ get
+ {
+ var items = new int[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<int, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public long[] Int64View
+ {
+ get
+ {
+ var items = new long[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<long, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public sbyte[] SByteView
+ {
+ get
+ {
+ var items = new sbyte[16];
+ Unsafe.WriteUnaligned(ref Unsafe.As<sbyte, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public float[] SingleView
+ {
+ get
+ {
+ var items = new float[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<float, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ushort[] UInt16View
+ {
+ get
+ {
+ var items = new ushort[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ushort, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public uint[] UInt32View
+ {
+ get
+ {
+ var items = new uint[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<uint, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ulong[] UInt64View
+ {
+ get
+ {
+ var items = new ulong[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ulong, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs
new file mode 100644
index 000000000..48744bb5e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs
@@ -0,0 +1,46 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ [Intrinsic]
+ [DebuggerDisplay("{DisplayString,nq}")]
+ [DebuggerTypeProxy(typeof(Vector256DebugView<>))]
+ [StructLayout(LayoutKind.Sequential, Size = 32)]
+ public readonly struct Vector256<T> where T : struct
+ {
+ // These fields exist to ensure the alignment is 8, rather than 1.
+ // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
+ private readonly ulong _00;
+ private readonly ulong _01;
+ private readonly ulong _02;
+ private readonly ulong _03;
+
+ private unsafe string DisplayString
+ {
+ get
+ {
+ // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr`
+ // which are not actually supported by any current architecture. This shouldn't be
+ // an issue however and greatly simplifies the check
+
+ if (typeof(T).IsPrimitive)
+ {
+ var items = new T[32 / Unsafe.SizeOf<T>()];
+ Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref items[0]), this);
+ return $"({string.Join(", ", items)})";
+ }
+ else
+ {
+ return SR.NotSupported_Type;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs
new file mode 100644
index 000000000..5131341ad
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs
@@ -0,0 +1,118 @@
+// 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 Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ internal readonly struct Vector256DebugView<T> where T : struct
+ {
+ private readonly Vector256<T> _value;
+
+ public Vector256DebugView(Vector256<T> value)
+ {
+ _value = value;
+ }
+
+ public byte[] ByteView
+ {
+ get
+ {
+ var items = new byte[32];
+ Unsafe.WriteUnaligned(ref items[0], _value);
+ return items;
+ }
+ }
+
+ public double[] DoubleView
+ {
+ get
+ {
+ var items = new double[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<double, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public short[] Int16View
+ {
+ get
+ {
+ var items = new short[16];
+ Unsafe.WriteUnaligned(ref Unsafe.As<short, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public int[] Int32View
+ {
+ get
+ {
+ var items = new int[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<int, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public long[] Int64View
+ {
+ get
+ {
+ var items = new long[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<long, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public sbyte[] SByteView
+ {
+ get
+ {
+ var items = new sbyte[32];
+ Unsafe.WriteUnaligned(ref Unsafe.As<sbyte, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public float[] SingleView
+ {
+ get
+ {
+ var items = new float[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<float, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ushort[] UInt16View
+ {
+ get
+ {
+ var items = new ushort[16];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ushort, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public uint[] UInt32View
+ {
+ get
+ {
+ var items = new uint[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<uint, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ulong[] UInt64View
+ {
+ get
+ {
+ var items = new ulong[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ulong, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs
new file mode 100644
index 000000000..8ce90b9d0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs
@@ -0,0 +1,43 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ [Intrinsic]
+ [DebuggerDisplay("{DisplayString,nq}")]
+ [DebuggerTypeProxy(typeof(Vector64DebugView<>))]
+ [StructLayout(LayoutKind.Sequential, Size = 8)]
+ public readonly struct Vector64<T> where T : struct
+ {
+ // These fields exist to ensure the alignment is 8, rather than 1.
+ // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
+ private readonly ulong _00;
+
+ private unsafe string DisplayString
+ {
+ get
+ {
+ // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr`
+ // which are not actually supported by any current architecture. This shouldn't be
+ // an issue however and greatly simplifies the check
+
+ if (typeof(T).IsPrimitive)
+ {
+ var items = new T[8 / Unsafe.SizeOf<T>()];
+ Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref items[0]), this);
+ return $"({string.Join(", ", items)})";
+ }
+ else
+ {
+ return SR.NotSupported_Type;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs
new file mode 100644
index 000000000..878e29949
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs
@@ -0,0 +1,118 @@
+// 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 Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ internal readonly struct Vector64DebugView<T> where T : struct
+ {
+ private readonly Vector64<T> _value;
+
+ public Vector64DebugView(Vector64<T> value)
+ {
+ _value = value;
+ }
+
+ public byte[] ByteView
+ {
+ get
+ {
+ var items = new byte[8];
+ Unsafe.WriteUnaligned(ref items[0], _value);
+ return items;
+ }
+ }
+
+ public double[] DoubleView
+ {
+ get
+ {
+ var items = new double[1];
+ Unsafe.WriteUnaligned(ref Unsafe.As<double, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public short[] Int16View
+ {
+ get
+ {
+ var items = new short[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<short, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public int[] Int32View
+ {
+ get
+ {
+ var items = new int[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<int, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public long[] Int64View
+ {
+ get
+ {
+ var items = new long[1];
+ Unsafe.WriteUnaligned(ref Unsafe.As<long, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public sbyte[] SByteView
+ {
+ get
+ {
+ var items = new sbyte[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<sbyte, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public float[] SingleView
+ {
+ get
+ {
+ var items = new float[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<float, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ushort[] UInt16View
+ {
+ get
+ {
+ var items = new ushort[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ushort, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public uint[] UInt32View
+ {
+ get
+ {
+ var items = new uint[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<uint, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ulong[] UInt64View
+ {
+ get
+ {
+ var items = new ulong[1];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ulong, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
new file mode 100644
index 000000000..d439defd7
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
@@ -0,0 +1,58 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AES hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Aes : Sse2
+ {
+ internal Aes() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
+ /// AESDEC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesdeclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESDECLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> DecryptLast(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesenc_si128 (__m128i a, __m128i RoundKey)
+ /// AESENC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesenclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESENCLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> EncryptLast(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesimc_si128 (__m128i a)
+ /// AESIMC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aeskeygenassist_si128 (__m128i a, const int imm8)
+ /// AESKEYGENASSIST xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> KeygenAssist(Vector128<byte> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ }
+
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs
new file mode 100644
index 000000000..412a0c2f1
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs
@@ -0,0 +1,58 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AES hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Aes : Sse2
+ {
+ internal Aes() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
+ /// AESDEC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) => Decrypt(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesdeclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESDECLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> DecryptLast(Vector128<byte> value, Vector128<byte> roundKey) => DecryptLast(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesenc_si128 (__m128i a, __m128i RoundKey)
+ /// AESENC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) => Encrypt(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesenclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESENCLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> EncryptLast(Vector128<byte> value, Vector128<byte> roundKey) => EncryptLast(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesimc_si128 (__m128i a)
+ /// AESIMC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) => InverseMixColumns(value);
+
+ /// <summary>
+ /// __m128i _mm_aeskeygenassist_si128 (__m128i a, const int imm8)
+ /// AESKEYGENASSIST xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> KeygenAssist(Vector128<byte> value, byte control) => KeygenAssist(value, control);
+
+ }
+
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
new file mode 100644
index 000000000..d6597cfb5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
@@ -0,0 +1,1230 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx : Sse42
+ {
+ internal Avx() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m256 _mm256_add_ps (__m256 a, __m256 b)
+ /// VADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Add(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_add_pd (__m256d a, __m256d b)
+ /// VADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Add(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_addsub_ps (__m256 a, __m256 b)
+ /// VADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AddSubtract(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_addsub_pd (__m256d a, __m256d b)
+ /// VADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AddSubtract(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_and_ps (__m256 a, __m256 b)
+ /// VANDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> And(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_and_pd (__m256d a, __m256d b)
+ /// VANDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> And(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_andnot_ps (__m256 a, __m256 b)
+ /// VANDNPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AndNot(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_andnot_pd (__m256d a, __m256d b)
+ /// VANDNPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AndNot(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8)
+ /// VBLENDPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Blend(Vector256<float> left, Vector256<float> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_blend_pd (__m256d a, __m256d b, const int imm8)
+ /// VBLENDPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Blend(Vector256<double> left, Vector256<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_blendv_ps (__m256 a, __m256 b, __m256 mask)
+ /// VBLENDVPS ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<float> BlendVariable(Vector256<float> left, Vector256<float> right, Vector256<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask)
+ /// VBLENDVPD ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<double> BlendVariable(Vector256<double> left, Vector256<double> right, Vector256<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> BroadcastScalarToVector128(float* source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS ymm, m32
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastScalarToVector256(float* source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_broadcast_sd (double const * mem_addr)
+ /// VBROADCASTSD ymm, m64
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastScalarToVector256(double* source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ps (__m128 const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastVector128ToVector256(float* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_broadcast_pd (__m128d const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastVector128ToVector256(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_ceil_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> Ceiling(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_ceil_pd (__m256d a)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> Ceiling(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmp_ps (__m128 a, __m128 b, const int imm8)
+ /// VCMPPS xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Compare(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmp_pd (__m128d a, __m128d b, const int imm8)
+ /// VCMPPD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Compare(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_cmp_ps (__m256 a, __m256 b, const int imm8)
+ /// VCMPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Compare(Vector256<float> left, Vector256<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmp_pd (__m256d a, __m256d b, const int imm8)
+ /// VCMPPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Compare(Vector256<double> left, Vector256<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmp_sd (__m128d a, __m128d b, const int imm8)
+ /// VCMPSS xmm, xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<double> CompareScalar(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cmp_ss (__m128 a, __m128 b, const int imm8)
+ /// VCMPSD xmm, xmm, xmm/m64, imm8
+ /// </summary>
+ public static Vector128<float> CompareScalar(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float _mm256_cvtss_f32 (__m256 a)
+ /// HELPER: VMOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_cvtpd_epi32 (__m256d a)
+ /// VCVTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_cvtpd_ps (__m256d a)
+ /// VCVTPD2PS xmm, ymm/m256
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtps_epi32 (__m256 a)
+ /// VCVTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_cvtepi32_ps (__m256i a)
+ /// VCVTDQ2PS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ConvertToVector256Single(Vector256<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cvtps_pd (__m128 a)
+ /// VCVTPS2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cvtepi32_pd (__m128i a)
+ /// VCVTDQ2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_cvttpd_epi32 (__m256d a)
+ /// VCVTTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvttps_epi32 (__m256 a)
+ /// VCVTTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32WithTruncation(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_div_ps (__m256 a, __m256 b)
+ /// VDIVPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Divide(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_div_pd (__m256d a, __m256d b)
+ /// VDIVPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Divide(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_dp_ps (__m256 a, __m256 b, const int imm8)
+ /// VDPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> DotProduct(Vector256<float> left, Vector256<float> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_moveldup_ps (__m256 a)
+ /// VMOVSLDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateEvenIndexed(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_movedup_pd (__m256d a)
+ /// VMOVDDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> DuplicateEvenIndexed(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_movehdup_ps (__m256 a)
+ /// VMOVSHDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateOddIndexed(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __int8 _mm256_extract_epi8 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static byte Extract(Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int16 _mm256_extract_epi16 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ushort Extract(Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static int Extract(Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static uint Extract(Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static long Extract(Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ulong Extract(Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// </summary>
+ public static Vector128<T> ExtractVector128<T>(Vector256<T> value, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(float* address, Vector256<float> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(double* address, Vector256<double> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256d _mm256_castpd128_pd256 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castps128_ps256 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castsi128_si256 (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<T> ExtendToVector256<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_floor_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> Floor(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_floor_pd (__m256d a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> Floor(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm256_castpd256_pd128 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m128 _mm256_castps256_ps128 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm256_castsi256_si128 (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<T> GetLowerHalf<T>(Vector256<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_hadd_ps (__m256 a, __m256 b)
+ /// VHADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalAdd(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_hadd_pd (__m256d a, __m256d b)
+ /// VHADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalAdd(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_hsub_ps (__m256 a, __m256 b)
+ /// VHSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalSubtract(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_hsub_pd (__m256d a, __m256d b)
+ /// VHSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalSubtract(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> Insert(Vector256<sbyte> value, sbyte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> Insert(Vector256<byte> value, byte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> Insert(Vector256<short> value, short data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> Insert(Vector256<ushort> value, ushort data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> Insert(Vector256<int> value, int data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> Insert(Vector256<uint> value, uint data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> Insert(Vector256<long> value, long data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> Insert(Vector256<ulong> value, ulong data, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// </summary>
+ public static Vector256<T> InsertVector128<T>(Vector256<T> value, Vector128<T> data, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<float> InsertVector128(Vector256<float> value, float* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<double> InsertVector128(Vector256<double> value, double* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_loadu_ps (float const * mem_addr)
+ /// VMOVUPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadVector256(float* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_loadu_pd (double const * mem_addr)
+ /// VMOVUPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadVector256(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_load_ps (float const * mem_addr)
+ /// VMOVAPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadAlignedVector256(float* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_load_pd (double const * mem_addr)
+ /// VMOVAPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadAlignedVector256(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadDquVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadDquVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadDquVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadDquVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadDquVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadDquVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadDquVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadDquVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_maskload_ps (float const * mem_addr, __m128i mask)
+ /// VMASKMOVPS xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> MaskLoad(float* address, Vector128<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_maskload_pd (double const * mem_addr, __m128i mask)
+ /// VMASKMOVPD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> MaskLoad(double* address, Vector128<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask)
+ /// VMASKMOVPS ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<float> MaskLoad(float* address, Vector256<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_maskload_pd (double const * mem_addr, __m256i mask)
+ /// VMASKMOVPD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<double> MaskLoad(double* address, Vector256<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a)
+ /// VMASKMOVPS m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector128<float> mask, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_pd (double * mem_addr, __m128i mask, __m128d a)
+ /// VMASKMOVPD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector128<double> mask, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a)
+ /// VMASKMOVPS m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector256<float> mask, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_pd (double * mem_addr, __m256i mask, __m256d a)
+ /// VMASKMOVPD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector256<double> mask, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_max_ps (__m256 a, __m256 b)
+ /// VMAXPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Max(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_max_pd (__m256d a, __m256d b)
+ /// VMAXPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Max(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_min_ps (__m256 a, __m256 b)
+ /// VMINPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Min(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_min_pd (__m256d a, __m256d b)
+ /// VMINPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Min(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_movemask_ps (__m256 a)
+ /// VMOVMSKPS reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_movemask_pd (__m256d a)
+ /// VMOVMSKPD reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_mul_ps (__m256 a, __m256 b)
+ /// VMULPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Multiply(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_mul_pd (__m256d a, __m256d b)
+ /// VMULPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Multiply(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_or_ps (__m256 a, __m256 b)
+ /// VORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Or(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_or_pd (__m256d a, __m256d b)
+ /// VORPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Or(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_permute_ps (__m128 a, int imm8)
+ /// VPERMILPS xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<float> Permute(Vector128<float> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_permute_pd (__m128d a, int imm8)
+ /// VPERMILPD xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<double> Permute(Vector128<double> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_permute_ps (__m256 a, int imm8)
+ /// VPERMILPS ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<float> Permute(Vector256<float> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_permute_pd (__m256d a, int imm8)
+ /// VPERMILPD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<double> Permute(Vector256<double> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256d _mm256_permute2f128_pd (__m256d a, __m256d b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<T> Permute2x128<T>(Vector256<T> left, Vector256<T> right, byte control) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_permutevar_ps (__m128 a, __m128i b)
+ /// VPERMILPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> PermuteVar(Vector128<float> left, Vector128<int> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_permutevar_pd (__m128d a, __m128i b)
+ /// VPERMILPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> PermuteVar(Vector128<double> left, Vector128<long> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_permutevar_ps (__m256 a, __m256i b)
+ /// VPERMILPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> PermuteVar(Vector256<float> left, Vector256<int> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_permutevar_pd (__m256d a, __m256i b)
+ /// VPERMILPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> PermuteVar(Vector256<double> left, Vector256<long> control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_rcp_ps (__m256 a)
+ /// VRCPPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Reciprocal(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_rsqrt_ps (__m256 a)
+ /// VRSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ReciprocalSqrt(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<float> RoundToNearestInteger(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> RoundToNegativeInfinity(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> RoundToPositiveInfinity(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<float> RoundToZero(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPS ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<float> RoundCurrentDirection(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<double> RoundToNearestInteger(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> RoundToNegativeInfinity(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> RoundToPositiveInfinity(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<double> RoundToZero(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPD ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<double> RoundCurrentDirection(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> SetVector256(sbyte e31, sbyte e30, sbyte e29, sbyte e28, sbyte e27, sbyte e26, sbyte e25, sbyte e24, sbyte e23, sbyte e22, sbyte e21, sbyte e20, sbyte e19, sbyte e18, sbyte e17, sbyte e16, sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> SetVector256(byte e31, byte e30, byte e29, byte e28, byte e27, byte e26, byte e25, byte e24, byte e23, byte e22, byte e21, byte e20, byte e19, byte e18, byte e17, byte e16, byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> SetVector256(short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> SetVector256(ushort e15, ushort e14, ushort e13, ushort e12, ushort e11, ushort e10, ushort e9, ushort e8, ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> SetVector256(int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> SetVector256(uint e7, uint e6, uint e5, uint e4, uint e3, uint e2, uint e1, uint e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> SetVector256(long e3, long e2, long e1, long e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> SetVector256(ulong e3, ulong e2, ulong e1, ulong e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<float> SetVector256(float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_set_pd (double e3, double e2, double e1, double e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<double> SetVector256(double e3, double e2, double e1, double e0) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_set1_epi8 (char a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi16 (short a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi32 (int a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi64x (long long a)
+ /// HELPER
+ /// __m256 _mm256_set1_ps (float a)
+ /// HELPER
+ /// __m256d _mm256_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetAllVector256<T>(T value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_set_m128 (__m128 hi, __m128 lo)
+ /// HELPER
+ /// __m256d _mm256_set_m128d (__m128d hi, __m128d lo)
+ /// HELPER
+ /// __m256i _mm256_set_m128i (__m128i hi, __m128i lo)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetHighLow<T>(Vector128<T> hi, Vector128<T> lo) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_setzero_si256 (void)
+ /// HELPER
+ /// __m256 _mm256_setzero_ps (void)
+ /// HELPER
+ /// __m256d _mm256_setzero_pd (void)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetZeroVector256<T>() where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_shuffle_ps (__m256 a, __m256 b, const int imm8)
+ /// VSHUFPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Shuffle(Vector256<float> value, Vector256<float> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_shuffle_pd (__m256d a, __m256d b, const int imm8)
+ /// VSHUFPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Shuffle(Vector256<double> value, Vector256<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_sqrt_ps (__m256 a)
+ /// VSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Sqrt(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_sqrt_pd (__m256d a)
+ /// VSQRTPD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Sqrt(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_castpd_ps (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castpd_si256 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castps_pd (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castps_si256 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castsi256_pd (__m256i a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castsi256_ps (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<U> StaticCast<T, U>(Vector256<T> value) where T : struct where U : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector256<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector256<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector256<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector256<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_ps (float * mem_addr, __m256 a)
+ /// VMOVAPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_pd (double * mem_addr, __m256d a)
+ /// VMOVAPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector256<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector256<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector256<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector256<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_ps (float * mem_addr, __m256 a)
+ /// MOVNTPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_pd (double * mem_addr, __m256d a)
+ /// MOVNTPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector256<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector256<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector256<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector256<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_ps (float * mem_addr, __m256 a)
+ /// MOVUPS m256, ymm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_pd (double * mem_addr, __m256d a)
+ /// MOVUPD m256, ymm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_sub_ps (__m256 a, __m256 b)
+ /// VSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Subtract(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_sub_pd (__m256d a, __m256d b)
+ /// VSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Subtract(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_testc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_testc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testc_pd (__m256d a, __m256d b)
+ /// VTESTPS ymm, ymm/m256
+ /// </summary>
+ public static bool TestC<T>(Vector256<T> left, Vector256<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testnzc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_testnzc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_testnzc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testnzc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testnzc_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestNotZAndNotC<T>(Vector256<T> left, Vector256<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testz_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_testz_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_testz_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testz_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testz_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestZ<T>(Vector256<T> left, Vector256<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_unpackhi_ps (__m256 a, __m256 b)
+ /// VUNPCKHPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackHigh(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_unpackhi_pd (__m256d a, __m256d b)
+ /// VUNPCKHPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackHigh(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_unpacklo_ps (__m256 a, __m256 b)
+ /// VUNPCKLPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackLow(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_unpacklo_pd (__m256d a, __m256d b)
+ /// VUNPCKLPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackLow(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_xor_ps (__m256 a, __m256 b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Xor(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_xor_pd (__m256d a, __m256d b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Xor(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs
new file mode 100644
index 000000000..3cb6849a6
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs
@@ -0,0 +1,1412 @@
+// 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.Runtime.Intrinsics;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx : Sse42
+ {
+ internal Avx() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m256 _mm256_add_ps (__m256 a, __m256 b)
+ /// VADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Add(Vector256<float> left, Vector256<float> right) => Add(left, right);
+ /// <summary>
+ /// __m256d _mm256_add_pd (__m256d a, __m256d b)
+ /// VADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Add(Vector256<double> left, Vector256<double> right) => Add(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_addsub_ps (__m256 a, __m256 b)
+ /// VADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AddSubtract(Vector256<float> left, Vector256<float> right) => AddSubtract(left, right);
+ /// <summary>
+ /// __m256d _mm256_addsub_pd (__m256d a, __m256d b)
+ /// VADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AddSubtract(Vector256<double> left, Vector256<double> right) => AddSubtract(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_and_ps (__m256 a, __m256 b)
+ /// VANDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> And(Vector256<float> left, Vector256<float> right) => And(left, right);
+ /// <summary>
+ /// __m256d _mm256_and_pd (__m256d a, __m256d b)
+ /// VANDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> And(Vector256<double> left, Vector256<double> right) => And(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_andnot_ps (__m256 a, __m256 b)
+ /// VANDNPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AndNot(Vector256<float> left, Vector256<float> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256d _mm256_andnot_pd (__m256d a, __m256d b)
+ /// VANDNPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AndNot(Vector256<double> left, Vector256<double> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8)
+ /// VBLENDPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Blend(Vector256<float> left, Vector256<float> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256d _mm256_blend_pd (__m256d a, __m256d b, const int imm8)
+ /// VBLENDPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Blend(Vector256<double> left, Vector256<double> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m256 _mm256_blendv_ps (__m256 a, __m256 b, __m256 mask)
+ /// VBLENDVPS ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<float> BlendVariable(Vector256<float> left, Vector256<float> right, Vector256<float> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask)
+ /// VBLENDVPD ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<double> BlendVariable(Vector256<double> left, Vector256<double> right, Vector256<double> mask) => BlendVariable(left, right, mask);
+
+ /// <summary>
+ /// __m128 _mm_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> BroadcastScalarToVector128(float* source) => BroadcastScalarToVector128(source);
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS ymm, m32
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastScalarToVector256(float* source) => BroadcastScalarToVector256(source);
+ /// <summary>
+ /// __m256d _mm256_broadcast_sd (double const * mem_addr)
+ /// VBROADCASTSD ymm, m64
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastScalarToVector256(double* source) => BroadcastScalarToVector256(source);
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ps (__m128 const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastVector128ToVector256(float* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256d _mm256_broadcast_pd (__m128d const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastVector128ToVector256(double* address) => BroadcastVector128ToVector256(address);
+
+ /// <summary>
+ /// __m256 _mm256_ceil_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> Ceiling(Vector256<float> value) => Ceiling(value);
+ /// <summary>
+ /// __m256d _mm256_ceil_pd (__m256d a)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> Ceiling(Vector256<double> value) => Ceiling(value);
+
+ /// <summary>
+ /// __m128 _mm_cmp_ps (__m128 a, __m128 b, const int imm8)
+ /// VCMPPS xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Compare(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m128d _mm_cmp_pd (__m128d a, __m128d b, const int imm8)
+ /// VCMPPD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Compare(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m256 _mm256_cmp_ps (__m256 a, __m256 b, const int imm8)
+ /// VCMPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Compare(Vector256<float> left, Vector256<float> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m256d _mm256_cmp_pd (__m256d a, __m256d b, const int imm8)
+ /// VCMPPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Compare(Vector256<double> left, Vector256<double> right, FloatComparisonMode mode) => Compare(left, right, mode);
+
+ /// <summary>
+ /// __m128d _mm_cmp_sd (__m128d a, __m128d b, const int imm8)
+ /// VCMPSS xmm, xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<double> CompareScalar(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) => CompareScalar(left, right, mode);
+ /// <summary>
+ /// __m128 _mm_cmp_ss (__m128 a, __m128 b, const int imm8)
+ /// VCMPSD xmm, xmm, xmm/m64, imm8
+ /// </summary>
+ public static Vector128<float> CompareScalar(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) => CompareScalar(left, right, mode);
+
+ /// <summary>
+ /// float _mm256_cvtss_f32 (__m256 a)
+ /// HELPER: VMOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector256<float> value) => ConvertToSingle(value);
+
+ /// <summary>
+ /// __m128i _mm256_cvtpd_epi32 (__m256d a)
+ /// VCVTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector256<double> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128 _mm256_cvtpd_ps (__m256d a)
+ /// VCVTPD2PS xmm, ymm/m256
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector256<double> value) => ConvertToVector128Single(value);
+ /// <summary>
+ /// __m256i _mm256_cvtps_epi32 (__m256 a)
+ /// VCVTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector256<float> value) => ConvertToVector256Int32(value);
+ /// <summary>
+ /// __m256 _mm256_cvtepi32_ps (__m256i a)
+ /// VCVTDQ2PS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ConvertToVector256Single(Vector256<int> value) => ConvertToVector256Single(value);
+ /// <summary>
+ /// __m256d _mm256_cvtps_pd (__m128 a)
+ /// VCVTPS2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<float> value) => ConvertToVector256Double(value);
+ /// <summary>
+ /// __m256d _mm256_cvtepi32_pd (__m128i a)
+ /// VCVTDQ2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<int> value) => ConvertToVector256Double(value);
+
+ /// <summary>
+ /// __m128i _mm256_cvttpd_epi32 (__m256d a)
+ /// VCVTTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector256<double> value) => ConvertToVector128Int32WithTruncation(value);
+ /// <summary>
+ /// __m256i _mm256_cvttps_epi32 (__m256 a)
+ /// VCVTTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32WithTruncation(Vector256<float> value) => ConvertToVector256Int32WithTruncation(value);
+
+ /// <summary>
+ /// __m256 _mm256_div_ps (__m256 a, __m256 b)
+ /// VDIVPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Divide(Vector256<float> left, Vector256<float> right) => Divide(left, right);
+ /// <summary>
+ /// __m256d _mm256_div_pd (__m256d a, __m256d b)
+ /// VDIVPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Divide(Vector256<double> left, Vector256<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_dp_ps (__m256 a, __m256 b, const int imm8)
+ /// VDPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> DotProduct(Vector256<float> left, Vector256<float> right, byte control) => DotProduct(left, right, control);
+
+ /// <summary>
+ /// __m256 _mm256_moveldup_ps (__m256 a)
+ /// VMOVSLDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateEvenIndexed(Vector256<float> value) => DuplicateEvenIndexed(value);
+ /// <summary>
+ /// __m256d _mm256_movedup_pd (__m256d a)
+ /// VMOVDDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> DuplicateEvenIndexed(Vector256<double> value) => DuplicateEvenIndexed(value);
+
+ /// <summary>
+ /// __m256 _mm256_movehdup_ps (__m256 a)
+ /// VMOVSHDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateOddIndexed(Vector256<float> value) => DuplicateOddIndexed(value);
+
+ /// <summary>
+ /// __int8 _mm256_extract_epi8 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static byte Extract(Vector256<byte> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<byte>(ref Unsafe.As<Vector256<byte>, byte>(ref value), index & 0x1F);
+ }
+
+
+ /// <summary>
+ /// __int16 _mm256_extract_epi16 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ushort Extract(Vector256<ushort> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<ushort>(ref Unsafe.As<Vector256<ushort>, ushort>(ref value), index & 0xF);
+ }
+
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static int Extract(Vector256<int> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<int>(ref Unsafe.As<Vector256<int>, int>(ref value), index & 0x7);
+ }
+
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static uint Extract(Vector256<uint> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<uint>(ref Unsafe.As<Vector256<uint>, uint>(ref value), index & 0x7);
+ }
+
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static long Extract(Vector256<long> value, byte index)
+ {
+ if (!IsSupported || (IntPtr.Size != 8))
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<long>(ref Unsafe.As<Vector256<long>, long>(ref value), index & 0x3);
+ }
+
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ulong Extract(Vector256<ulong> value, byte index)
+ {
+ if (!IsSupported || (IntPtr.Size != 8))
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<ulong>(ref Unsafe.As<Vector256<ulong>, ulong>(ref value), index & 0x3);
+ }
+
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// </summary>
+ public static Vector128<T> ExtractVector128<T>(Vector256<T> value, byte index) where T : struct
+ {
+ return ExtractVector128<T>(value, index);
+ }
+
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(float* address, Vector256<float> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(double* address, Vector256<double> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m256d _mm256_castpd128_pd256 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castps128_ps256 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castsi128_si256 (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<T> ExtendToVector256<T>(Vector128<T> value) where T : struct
+ {
+ return ExtendToVector256<T>(value);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_floor_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> Floor(Vector256<float> value) => Floor(value);
+ /// <summary>
+ /// __m256d _mm256_floor_pd (__m256d a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> Floor(Vector256<double> value) => Floor(value);
+
+ /// <summary>
+ /// __m128d _mm256_castpd256_pd128 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m128 _mm256_castps256_ps128 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm256_castsi256_si128 (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<T> GetLowerHalf<T>(Vector256<T> value) where T : struct
+ {
+ return GetLowerHalf<T>(value);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_hadd_ps (__m256 a, __m256 b)
+ /// VHADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalAdd(Vector256<float> left, Vector256<float> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m256d _mm256_hadd_pd (__m256d a, __m256d b)
+ /// VHADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalAdd(Vector256<double> left, Vector256<double> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_hsub_ps (__m256 a, __m256 b)
+ /// VHSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalSubtract(Vector256<float> left, Vector256<float> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m256d _mm256_hsub_pd (__m256d a, __m256d b)
+ /// VHSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalSubtract(Vector256<double> left, Vector256<double> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> Insert(Vector256<sbyte> value, sbyte data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x1F;
+ sbyte* buffer = stackalloc sbyte[32];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> Insert(Vector256<byte> value, byte data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x1F;
+ byte* buffer = stackalloc byte[32];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> Insert(Vector256<short> value, short data, byte index)
+ {
+ unsafe
+ {
+ index &= 0xF;
+ short* buffer = stackalloc short[16];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> Insert(Vector256<ushort> value, ushort data, byte index)
+ {
+ unsafe
+ {
+ index &= 0xF;
+ ushort* buffer = stackalloc ushort[16];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> Insert(Vector256<int> value, int data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x7;
+ int* buffer = stackalloc int[8];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> Insert(Vector256<uint> value, uint data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x7;
+ uint* buffer = stackalloc uint[8];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> Insert(Vector256<long> value, long data, byte index)
+ {
+ if (IntPtr.Size != 8)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ unsafe
+ {
+ index &= 0x3;
+ long* buffer = stackalloc long[4];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> Insert(Vector256<ulong> value, ulong data, byte index)
+ {
+ if (IntPtr.Size != 8)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ unsafe
+ {
+ index &= 0x3;
+ ulong* buffer = stackalloc ulong[4];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// </summary>
+ public static Vector256<T> InsertVector128<T>(Vector256<T> value, Vector128<T> data, byte index) where T : struct
+ {
+ return InsertVector128<T>(value, data, index);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<float> InsertVector128(Vector256<float> value, float* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<double> InsertVector128(Vector256<double> value, double* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadVector256(sbyte* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadVector256(byte* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadVector256(short* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadVector256(ushort* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadVector256(int* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadVector256(uint* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadVector256(long* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadVector256(ulong* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256 _mm256_loadu_ps (float const * mem_addr)
+ /// VMOVUPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadVector256(float* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256d _mm256_loadu_pd (double const * mem_addr)
+ /// VMOVUPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadVector256(double* address) => LoadVector256(address);
+
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256(sbyte* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256(byte* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256(short* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256(ushort* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256(int* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256(uint* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256(long* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256(ulong* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256 _mm256_load_ps (float const * mem_addr)
+ /// VMOVAPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadAlignedVector256(float* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256d _mm256_load_pd (double const * mem_addr)
+ /// VMOVAPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadAlignedVector256(double* address) => LoadAlignedVector256(address);
+
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadDquVector256(sbyte* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadDquVector256(byte* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadDquVector256(short* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadDquVector256(ushort* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadDquVector256(int* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadDquVector256(uint* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadDquVector256(long* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadDquVector256(ulong* address) => LoadDquVector256(address);
+
+ /// <summary>
+ /// __m128 _mm_maskload_ps (float const * mem_addr, __m128i mask)
+ /// VMASKMOVPS xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> MaskLoad(float* address, Vector128<float> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128d _mm_maskload_pd (double const * mem_addr, __m128i mask)
+ /// VMASKMOVPD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> MaskLoad(double* address, Vector128<double> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// __m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask)
+ /// VMASKMOVPS ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<float> MaskLoad(float* address, Vector256<float> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256d _mm256_maskload_pd (double const * mem_addr, __m256i mask)
+ /// VMASKMOVPD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<double> MaskLoad(double* address, Vector256<double> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a)
+ /// VMASKMOVPS m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector128<float> mask, Vector128<float> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_pd (double * mem_addr, __m128i mask, __m128d a)
+ /// VMASKMOVPD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector128<double> mask, Vector128<double> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a)
+ /// VMASKMOVPS m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector256<float> mask, Vector256<float> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_pd (double * mem_addr, __m256i mask, __m256d a)
+ /// VMASKMOVPD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector256<double> mask, Vector256<double> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// __m256 _mm256_max_ps (__m256 a, __m256 b)
+ /// VMAXPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Max(Vector256<float> left, Vector256<float> right) => Max(left, right);
+ /// <summary>
+ /// __m256d _mm256_max_pd (__m256d a, __m256d b)
+ /// VMAXPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Max(Vector256<double> left, Vector256<double> right) => Max(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_min_ps (__m256 a, __m256 b)
+ /// VMINPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Min(Vector256<float> left, Vector256<float> right) => Min(left, right);
+ /// <summary>
+ /// __m256d _mm256_min_pd (__m256d a, __m256d b)
+ /// VMINPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Min(Vector256<double> left, Vector256<double> right) => Min(left, right);
+
+ /// <summary>
+ /// int _mm256_movemask_ps (__m256 a)
+ /// VMOVMSKPS reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<float> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm256_movemask_pd (__m256d a)
+ /// VMOVMSKPD reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<double> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m256 _mm256_mul_ps (__m256 a, __m256 b)
+ /// VMULPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Multiply(Vector256<float> left, Vector256<float> right) => Multiply(left, right);
+ /// <summary>
+ /// __m256d _mm256_mul_pd (__m256d a, __m256d b)
+ /// VMULPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Multiply(Vector256<double> left, Vector256<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_or_ps (__m256 a, __m256 b)
+ /// VORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Or(Vector256<float> left, Vector256<float> right) => Or(left, right);
+ /// <summary>
+ /// __m256d _mm256_or_pd (__m256d a, __m256d b)
+ /// VORPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Or(Vector256<double> left, Vector256<double> right) => Or(left, right);
+
+ /// <summary>
+ /// __m128 _mm_permute_ps (__m128 a, int imm8)
+ /// VPERMILPS xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<float> Permute(Vector128<float> value, byte control) => Permute(value, control);
+ /// <summary>
+ /// __m128d _mm_permute_pd (__m128d a, int imm8)
+ /// VPERMILPD xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<double> Permute(Vector128<double> value, byte control) => Permute(value, control);
+
+ /// <summary>
+ /// __m256 _mm256_permute_ps (__m256 a, int imm8)
+ /// VPERMILPS ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<float> Permute(Vector256<float> value, byte control) => Permute(value, control);
+ /// <summary>
+ /// __m256d _mm256_permute_pd (__m256d a, int imm8)
+ /// VPERMILPD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<double> Permute(Vector256<double> value, byte control) => Permute(value, control);
+
+ /// <summary>
+ /// __m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256d _mm256_permute2f128_pd (__m256d a, __m256d b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<T> Permute2x128<T>(Vector256<T> left, Vector256<T> right, byte control) where T : struct
+ {
+ return Permute2x128<T>(left, right, control);
+ }
+
+ /// <summary>
+ /// __m128 _mm_permutevar_ps (__m128 a, __m128i b)
+ /// VPERMILPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> PermuteVar(Vector128<float> left, Vector128<int> control) => PermuteVar(left, control);
+ /// <summary>
+ /// __m128d _mm_permutevar_pd (__m128d a, __m128i b)
+ /// VPERMILPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> PermuteVar(Vector128<double> left, Vector128<long> control) => PermuteVar(left, control);
+ /// <summary>
+ /// __m256 _mm256_permutevar_ps (__m256 a, __m256i b)
+ /// VPERMILPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> PermuteVar(Vector256<float> left, Vector256<int> control) => PermuteVar(left, control);
+ /// <summary>
+ /// __m256d _mm256_permutevar_pd (__m256d a, __m256i b)
+ /// VPERMILPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> PermuteVar(Vector256<double> left, Vector256<long> control) => PermuteVar(left, control);
+
+ /// <summary>
+ /// __m256 _mm256_rcp_ps (__m256 a)
+ /// VRCPPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Reciprocal(Vector256<float> value) => Reciprocal(value);
+
+ /// <summary>
+ /// __m256 _mm256_rsqrt_ps (__m256 a)
+ /// VRSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ReciprocalSqrt(Vector256<float> value) => ReciprocalSqrt(value);
+
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<float> RoundToNearestInteger(Vector256<float> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> RoundToNegativeInfinity(Vector256<float> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> RoundToPositiveInfinity(Vector256<float> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<float> RoundToZero(Vector256<float> value) => RoundToZero(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPS ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<float> RoundCurrentDirection(Vector256<float> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<double> RoundToNearestInteger(Vector256<double> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> RoundToNegativeInfinity(Vector256<double> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> RoundToPositiveInfinity(Vector256<double> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<double> RoundToZero(Vector256<double> value) => RoundToZero(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPD ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<double> RoundCurrentDirection(Vector256<double> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> SetVector256(sbyte e31, sbyte e30, sbyte e29, sbyte e28, sbyte e27, sbyte e26, sbyte e25, sbyte e24, sbyte e23, sbyte e22, sbyte e21, sbyte e20, sbyte e19, sbyte e18, sbyte e17, sbyte e16, sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0) => SetVector256(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> SetVector256(byte e31, byte e30, byte e29, byte e28, byte e27, byte e26, byte e25, byte e24, byte e23, byte e22, byte e21, byte e20, byte e19, byte e18, byte e17, byte e16, byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0) => SetVector256(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> SetVector256(short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) => SetVector256(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> SetVector256(ushort e15, ushort e14, ushort e13, ushort e12, ushort e11, ushort e10, ushort e9, ushort e8, ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0) => SetVector256(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> SetVector256(int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0) => SetVector256(e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> SetVector256(uint e7, uint e6, uint e5, uint e4, uint e3, uint e2, uint e1, uint e0) => SetVector256(e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> SetVector256(long e3, long e2, long e1, long e0) => SetVector256(e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> SetVector256(ulong e3, ulong e2, ulong e1, ulong e0) => SetVector256(e3, e2, e1, e0);
+ /// <summary>
+ /// __m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<float> SetVector256(float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0) => SetVector256(e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256d _mm256_set_pd (double e3, double e2, double e1, double e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<double> SetVector256(double e3, double e2, double e1, double e0) => SetVector256(e3, e2, e1, e0);
+
+ /// <summary>
+ /// __m256i _mm256_set1_epi8 (char a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi16 (short a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi32 (int a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi64x (long long a)
+ /// HELPER
+ /// __m256 _mm256_set1_ps (float a)
+ /// HELPER
+ /// __m256d _mm256_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetAllVector256<T>(T value) where T : struct
+ {
+ return SetAllVector256<T>(value);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_set_m128 (__m128 hi, __m128 lo)
+ /// HELPER
+ /// __m256d _mm256_set_m128d (__m128d hi, __m128d lo)
+ /// HELPER
+ /// __m256i _mm256_set_m128i (__m128i hi, __m128i lo)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetHighLow<T>(Vector128<T> hi, Vector128<T> lo) where T : struct
+ {
+ return SetHighLow<T>(hi, lo);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_setzero_si256 (void)
+ /// HELPER
+ /// __m256 _mm256_setzero_ps (void)
+ /// HELPER
+ /// __m256d _mm256_setzero_pd (void)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetZeroVector256<T>() where T : struct
+ {
+ return SetZeroVector256<T>();
+ }
+
+ /// <summary>
+ /// __m256 _mm256_shuffle_ps (__m256 a, __m256 b, const int imm8)
+ /// VSHUFPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Shuffle(Vector256<float> value, Vector256<float> right, byte control) => Shuffle(value, right, control);
+ /// <summary>
+ /// __m256d _mm256_shuffle_pd (__m256d a, __m256d b, const int imm8)
+ /// VSHUFPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Shuffle(Vector256<double> value, Vector256<double> right, byte control) => Shuffle(value, right, control);
+
+ /// <summary>
+ /// __m256 _mm256_sqrt_ps (__m256 a)
+ /// VSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Sqrt(Vector256<float> value) => Sqrt(value);
+ /// <summary>
+ /// __m256d _mm256_sqrt_pd (__m256d a)
+ /// VSQRTPD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Sqrt(Vector256<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// __m256 _mm256_castpd_ps (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castpd_si256 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castps_pd (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castps_si256 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castsi256_pd (__m256i a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castsi256_ps (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<U> StaticCast<T, U>(Vector256<T> value) where T : struct where U : struct
+ {
+ return StaticCast<T, U>(value);
+ }
+
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector256<sbyte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector256<byte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector256<short> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector256<ushort> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector256<int> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector256<uint> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector256<long> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector256<ulong> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_ps (float * mem_addr, __m256 a)
+ /// VMOVAPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector256<float> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_pd (double * mem_addr, __m256d a)
+ /// VMOVAPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector256<double> source) => StoreAligned(address, source);
+
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector256<sbyte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector256<byte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector256<short> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector256<ushort> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector256<int> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector256<uint> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector256<long> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector256<ulong> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_ps (float * mem_addr, __m256 a)
+ /// MOVNTPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector256<float> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_pd (double * mem_addr, __m256d a)
+ /// MOVNTPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector256<double> source) => StoreAlignedNonTemporal(address, source);
+
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector256<sbyte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector256<byte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector256<short> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector256<ushort> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector256<int> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector256<uint> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector256<long> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector256<ulong> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_ps (float * mem_addr, __m256 a)
+ /// MOVUPS m256, ymm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector256<float> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_pd (double * mem_addr, __m256d a)
+ /// MOVUPD m256, ymm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector256<double> source) => Store(address, source);
+
+ /// <summary>
+ /// __m256 _mm256_sub_ps (__m256 a, __m256 b)
+ /// VSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Subtract(Vector256<float> left, Vector256<float> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256d _mm256_sub_pd (__m256d a, __m256d b)
+ /// VSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Subtract(Vector256<double> left, Vector256<double> right) => Subtract(left, right);
+
+ /// <summary>
+ /// int _mm_testc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<float> left, Vector128<float> right) => TestC(left, right);
+ /// <summary>
+ /// int _mm_testc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<double> left, Vector128<double> right) => TestC(left, right);
+
+ /// <summary>
+ /// int _mm256_testc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testc_pd (__m256d a, __m256d b)
+ /// VTESTPS ymm, ymm/m256
+ /// </summary>
+ public static bool TestC<T>(Vector256<T> left, Vector256<T> right) where T : struct
+ {
+ return TestC<T>(left, right);
+ }
+
+ /// <summary>
+ /// int _mm_testnzc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<float> left, Vector128<float> right) => TestNotZAndNotC(left, right);
+ /// <summary>
+ /// int _mm_testnzc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<double> left, Vector128<double> right) => TestNotZAndNotC(left, right);
+
+ /// <summary>
+ /// int _mm256_testnzc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testnzc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testnzc_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestNotZAndNotC<T>(Vector256<T> left, Vector256<T> right) where T : struct
+ {
+ return TestNotZAndNotC<T>(left, right);
+ }
+
+ /// <summary>
+ /// int _mm_testz_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<float> left, Vector128<float> right) => TestZ(left, right);
+ /// <summary>
+ /// int _mm_testz_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<double> left, Vector128<double> right) => TestZ(left, right);
+
+ /// <summary>
+ /// int _mm256_testz_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testz_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testz_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestZ<T>(Vector256<T> left, Vector256<T> right) where T : struct
+ {
+ return TestZ<T>(left, right);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_unpackhi_ps (__m256 a, __m256 b)
+ /// VUNPCKHPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackHigh(Vector256<float> left, Vector256<float> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256d _mm256_unpackhi_pd (__m256d a, __m256d b)
+ /// VUNPCKHPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackHigh(Vector256<double> left, Vector256<double> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_unpacklo_ps (__m256 a, __m256 b)
+ /// VUNPCKLPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackLow(Vector256<float> left, Vector256<float> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256d _mm256_unpacklo_pd (__m256d a, __m256d b)
+ /// VUNPCKLPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackLow(Vector256<double> left, Vector256<double> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_xor_ps (__m256 a, __m256 b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Xor(Vector256<float> left, Vector256<float> right) => Xor(left, right);
+ /// <summary>
+ /// __m256d _mm256_xor_pd (__m256d a, __m256d b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Xor(Vector256<double> left, Vector256<double> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
new file mode 100644
index 000000000..79c30d37a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
@@ -0,0 +1,1915 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx2 : Avx
+ {
+ internal Avx2() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m256i _mm256_abs_epi8 (__m256i a)
+ /// VPABSB ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Abs(Vector256<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_abs_epi16 (__m256i a)
+ /// VPABSW ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Abs(Vector256<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_abs_epi32 (__m256i a)
+ /// VPABSD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Abs(Vector256<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Add(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Add(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Add(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Add(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Add(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Add(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Add(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Add(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_adds_epi8 (__m256i a, __m256i b)
+ /// VPADDSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AddSaturate(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_adds_epu8 (__m256i a, __m256i b)
+ /// VPADDUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AddSaturate(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_adds_epi16 (__m256i a, __m256i b)
+ /// VPADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AddSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_adds_epu16 (__m256i a, __m256i b)
+ /// VPADDUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AddSaturate(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_alignr_epi8 (__m256i a, __m256i b, const int count)
+ /// VPALIGNR ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> AlignRight(Vector256<sbyte> left, Vector256<sbyte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> And(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> And(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> And(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> And(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> And(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> And(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> And(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> And(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AndNot(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AndNot(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AndNot(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AndNot(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> AndNot(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> AndNot(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> AndNot(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> AndNot(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_avg_epu8 (__m256i a, __m256i b)
+ /// VPAVGB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Average(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_avg_epu16 (__m256i a, __m256i b)
+ /// VPAVGW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Average(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Blend(Vector128<int> left, Vector128<int> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Blend(Vector128<uint> left, Vector128<uint> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Blend(Vector256<short> left, Vector256<short> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Blend(Vector256<ushort> left, Vector256<ushort> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Blend(Vector256<int> left, Vector256<int> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Blend(Vector256<uint> left, Vector256<uint> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<sbyte> BlendVariable(Vector256<sbyte> left, Vector256<sbyte> right, Vector256<sbyte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<byte> BlendVariable(Vector256<byte> left, Vector256<byte> right, Vector256<byte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB xmm, xmm
+ /// __m128i _mm_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW xmm, xmm
+ /// __m128i _mm_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD xmm, xmm
+ /// __m128i _mm_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ xmm, xmm
+ /// __m128 _mm_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS xmm, xmm
+ /// __m128d _mm_broadcastsd_pd (__m128d a)
+ /// VMOVDDUP xmm, xmm
+ /// </summary>
+ public static Vector128<T> BroadcastScalarToVector128<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB ymm, xmm
+ /// __m256i _mm256_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW ymm, xmm
+ /// __m256i _mm256_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD ymm, xmm
+ /// __m256i _mm256_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ ymm, xmm
+ /// __m256 _mm256_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS ymm, xmm
+ /// __m256d _mm256_broadcastsd_pd (__m128d a)
+ /// VBROADCASTSD ymm, xmm
+ /// </summary>
+ public static Vector256<T> BroadcastScalarToVector256<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<sbyte> BroadcastVector128ToVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<byte> BroadcastVector128ToVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<short> BroadcastVector128ToVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<ushort> BroadcastVector128ToVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<int> BroadcastVector128ToVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<uint> BroadcastVector128ToVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<long> BroadcastVector128ToVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<ulong> BroadcastVector128ToVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareEqual(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> CompareEqual(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareEqual(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> CompareEqual(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareEqual(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> CompareEqual(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareEqual(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> CompareEqual(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi8 (__m256i a, __m256i b)
+ /// VPCMPGTB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareGreaterThan(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi16 (__m256i a, __m256i b)
+ /// VPCMPGTW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareGreaterThan(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi32 (__m256i a, __m256i b)
+ /// VPCMPGTD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareGreaterThan(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi64 (__m256i a, __m256i b)
+ /// VPCMPGTQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareGreaterThan(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// double _mm256_cvtsd_f64 (__m256d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector256<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector256<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi16 (__m128i a)
+ /// VPMOVSXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ConvertToVector256Int16(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi16 (__m128i a)
+ /// VPMOVZXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ConvertToVector256UInt16(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi32 (__m128i a)
+ /// VPMOVSXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi32 (__m128i a)
+ /// VPMOVSXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi32 (__m128i a)
+ /// VPMOVZXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi32 (__m128i a)
+ /// VPMOVZXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi64 (__m128i a)
+ /// VPMOVSXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi64 (__m128i a)
+ /// VPMOVSXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi32_epi64 (__m128i a)
+ /// VPMOVSXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi64 (__m128i a)
+ /// VPMOVZXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi64 (__m128i a)
+ /// VPMOVZXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu32_epi64 (__m128i a)
+ /// VPMOVZXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ExtractVector128(Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
+ // <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<byte> ExtractVector128(Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<short> ExtractVector128(Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ushort> ExtractVector128(Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<int> ExtractVector128(Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<uint> ExtractVector128(Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<long> ExtractVector128(Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ulong> ExtractVector128(Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_i32gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_i64gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_i64gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherVector256(int* baseAddress, Vector256<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherVector256(uint* baseAddress, Vector256<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_i32gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherVector256(float* baseAddress, Vector256<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_i64gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_i64gather_pd (double const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPD ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<int> index, Vector128<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<int> index, Vector128<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<int> index, Vector128<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<int> index, Vector128<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_mask_i32gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<int> index, Vector128<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_mask_i32gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<int> index, Vector128<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<long> index, Vector128<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<long> index, Vector128<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<long> index, Vector128<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<long> index, Vector128<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_mask_i64gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<long> index, Vector128<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_mask_i64gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<long> index, Vector128<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherMaskVector256(Vector256<int> source, int* baseAddress, Vector256<int> index, Vector256<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherMaskVector256(Vector256<uint> source, uint* baseAddress, Vector256<int> index, Vector256<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector128<int> index, Vector256<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector128<int> index, Vector256<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_mask_i32gather_ps (__m256 src, float const* base_addr, __m256i vindex, __m256 mask, const int scale)
+ /// VPGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherMaskVector256(Vector256<float> source, float* baseAddress, Vector256<int> index, Vector256<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_mask_i32gather_pd (__m256d src, double const* base_addr, __m128i vindex, __m256d mask, const int scale)
+ /// VPGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector128<int> index, Vector256<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector256<long> index, Vector128<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector256<long> index, Vector128<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector256<long> index, Vector256<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector256<long> index, Vector256<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_mask_i64gather_ps (__m128 src, float const* base_addr, __m256i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector256<long> index, Vector128<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_mask_i64gather_pd (__m256d src, double const* base_addr, __m256i vindex, __m256d mask, const int scale)
+ /// VGATHERQPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector256<long> index, Vector256<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hadd_epi16 (__m256i a, __m256i b)
+ /// VPHADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAdd(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_hadd_epi32 (__m256i a, __m256i b)
+ /// VPHADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalAdd(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hadds_epi16 (__m256i a, __m256i b)
+ /// VPHADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAddSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hsub_epi16 (__m256i a, __m256i b)
+ /// VPHSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtract(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_hsub_epi32 (__m256i a, __m256i b)
+ /// VPHSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalSubtract(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hsubs_epi16 (__m256i a, __m256i b)
+ /// VPHSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtractSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<sbyte> InsertVector128(Vector256<sbyte> value, Vector128<sbyte> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xm128, imm8
+ /// </summary>
+ public new static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<byte> InsertVector128(Vector256<byte> value, Vector128<byte> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<short> InsertVector128(Vector256<short> value, Vector128<short> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ushort> InsertVector128(Vector256<ushort> value, Vector128<ushort> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<int> InsertVector128(Vector256<int> value, Vector128<int> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<uint> InsertVector128(Vector256<uint> value, Vector128<uint> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<long> InsertVector128(Vector256<long> value, Vector128<long> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ulong> InsertVector128(Vector256<ulong> value, Vector128<ulong> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256NonTemporal(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256NonTemporal(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256NonTemporal(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256NonTemporal(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256NonTemporal(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256NonTemporal(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256NonTemporal(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256NonTemporal(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> MaskLoad(int* address, Vector128<int> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> MaskLoad(uint* address, Vector128<uint> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> MaskLoad(long* address, Vector128<long> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> MaskLoad(ulong* address, Vector128<ulong> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> MaskLoad(int* address, Vector256<int> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> MaskLoad(uint* address, Vector256<uint> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> MaskLoad(long* address, Vector256<long> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> MaskLoad(ulong* address, Vector256<ulong> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector128<int> mask, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector128<uint> mask, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector128<long> mask, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector128<ulong> mask, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector256<int> mask, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector256<uint> mask, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector256<long> mask, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector256<ulong> mask, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_madd_epi16 (__m256i a, __m256i b)
+ /// VPMADDWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyAddAdjacent(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_maddubs_epi16 (__m256i a, __m256i b)
+ /// VPMADDUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyAddAdjacent(Vector256<byte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_max_epi8 (__m256i a, __m256i b)
+ /// VPMAXSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Max(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epu8 (__m256i a, __m256i b)
+ /// VPMAXUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Max(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epi16 (__m256i a, __m256i b)
+ /// VPMAXSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Max(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epu16 (__m256i a, __m256i b)
+ /// VPMAXUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Max(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epi32 (__m256i a, __m256i b)
+ /// VPMAXSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Max(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epu32 (__m256i a, __m256i b)
+ /// VPMAXUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Max(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_min_epi8 (__m256i a, __m256i b)
+ /// VPMINSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Min(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epu8 (__m256i a, __m256i b)
+ /// VPMINUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Min(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epi16 (__m256i a, __m256i b)
+ /// VPMINSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Min(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epu16 (__m256i a, __m256i b)
+ /// VPMINUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Min(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epi32 (__m256i a, __m256i b)
+ /// VPMINSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Min(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epu32 (__m256i a, __m256i b)
+ /// VPMINUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Min(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<byte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mpsadbw_epu8 (__m256i a, __m256i b, const int imm8)
+ /// VMPSADBW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> MultipleSumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mul_epi32 (__m256i a, __m256i b)
+ /// VPMULDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Multiply(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mul_epu32 (__m256i a, __m256i b)
+ /// VPMULUDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Multiply(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mulhi_epi16 (__m256i a, __m256i b)
+ /// VPMULHW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHigh(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mulhi_epu16 (__m256i a, __m256i b)
+ /// VPMULHUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> MultiplyHigh(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mulhrs_epi16 (__m256i a, __m256i b)
+ /// VPMULHRSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHighRoundScale(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mullo_epi16 (__m256i a, __m256i b)
+ /// VPMULLW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyLow(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mullo_epi32 (__m256i a, __m256i b)
+ /// VPMULLD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyLow(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Or(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Or(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Or(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Or(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Or(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Or(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Or(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Or(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_packs_epi16 (__m256i a, __m256i b)
+ /// VPACKSSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> PackSignedSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_packs_epi32 (__m256i a, __m256i b)
+ /// VPACKSSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> PackSignedSaturate(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_packus_epi16 (__m256i a, __m256i b)
+ /// VPACKUSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> PackUnsignedSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_packus_epi32 (__m256i a, __m256i b)
+ /// VPACKUSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> PackUnsignedSaturate(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> Permute2x128(Vector256<sbyte> left, Vector256<sbyte> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<byte> Permute2x128(Vector256<byte> left, Vector256<byte> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Permute2x128(Vector256<short> left, Vector256<short> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Permute2x128(Vector256<ushort> left, Vector256<ushort> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Permute2x128(Vector256<int> left, Vector256<int> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Permute2x128(Vector256<uint> left, Vector256<uint> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute2x128(Vector256<long> left, Vector256<long> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute2x128(Vector256<ulong> left, Vector256<ulong> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute4x64(Vector256<long> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute4x64(Vector256<ulong> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_permute4x64_pd (__m256d a, const int imm8)
+ /// VPERMPD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Permute4x64(Vector256<double> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> PermuteVar8x32(Vector256<int> left, Vector256<int> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> PermuteVar8x32(Vector256<uint> left, Vector256<uint> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_permutevar8x32_ps (__m256 a, __m256i idx)
+ /// VPERMPS ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> PermuteVar8x32(Vector256<float> left, Vector256<int> control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftLeftLogical128BitLane(Vector256<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftLeftLogical128BitLane(Vector256<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical128BitLane(Vector256<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical128BitLane(Vector256<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical128BitLane(Vector256<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical128BitLane(Vector256<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical128BitLane(Vector256<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical128BitLane(Vector256<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogicalVariable(Vector256<int> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogicalVariable(Vector256<uint> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogicalVariable(Vector256<long> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogicalVariable(Vector128<int> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogicalVariable(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogicalVariable(Vector128<long> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// _mm256_sra_epi16 (__m256i a, __m128i count)
+ /// VPSRAW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _mm256_sra_epi32 (__m256i a, __m128i count)
+ /// VPSRAD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srai_epi16 (__m256i a, int imm8)
+ /// VPSRAW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srai_epi32 (__m256i a, int imm8)
+ /// VPSRAD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srav_epi32 (__m256i a, __m256i count)
+ /// VPSRAVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmeticVariable(Vector256<int> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srav_epi32 (__m128i a, __m128i count)
+ /// VPSRAVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmeticVariable(Vector128<int> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftRightLogical128BitLane(Vector256<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftRightLogical128BitLane(Vector256<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical128BitLane(Vector256<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical128BitLane(Vector256<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical128BitLane(Vector256<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical128BitLane(Vector256<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical128BitLane(Vector256<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical128BitLane(Vector256<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightLogicalVariable(Vector256<int> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogicalVariable(Vector256<uint> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftRightLogicalVariable(Vector256<long> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogicalVariable(Vector128<int> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogicalVariable(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogicalVariable(Vector128<long> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Shuffle(Vector256<sbyte> value, Vector256<sbyte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Shuffle(Vector256<byte> value, Vector256<byte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Shuffle(Vector256<int> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Shuffle(Vector256<uint> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleHigh(Vector256<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleHigh(Vector256<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleLow(Vector256<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleLow(Vector256<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sign_epi8 (__m256i a, __m256i b)
+ /// VPSIGNB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Sign(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sign_epi16 (__m256i a, __m256i b)
+ /// VPSIGNW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Sign(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sign_epi32 (__m256i a, __m256i b)
+ /// VPSIGND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Sign(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Subtract(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Subtract(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Subtract(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Subtract(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Subtract(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Subtract(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Subtract(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Subtract(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_subs_epi8 (__m256i a, __m256i b)
+ /// VPSUBSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> SubtractSaturate(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_subs_epi16 (__m256i a, __m256i b)
+ /// VPSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> SubtractSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_subs_epu8 (__m256i a, __m256i b)
+ /// VPSUBUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> SubtractSaturate(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_subs_epu16 (__m256i a, __m256i b)
+ /// VPSUBUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SubtractSaturate(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sad_epu8 (__m256i a, __m256i b)
+ /// VPSADBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackHigh(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackHigh(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackHigh(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackHigh(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackHigh(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackHigh(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackHigh(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackHigh(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackLow(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackLow(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackLow(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackLow(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackLow(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackLow(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackLow(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackLow(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Xor(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Xor(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Xor(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Xor(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Xor(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Xor(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Xor(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Xor(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs
new file mode 100644
index 000000000..90c5b315b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs
@@ -0,0 +1,2641 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx2 : Avx
+ {
+ internal Avx2() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m256i _mm256_abs_epi8 (__m256i a)
+ /// VPABSB ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Abs(Vector256<sbyte> value) => Abs(value);
+ /// <summary>
+ /// __m256i _mm256_abs_epi16 (__m256i a)
+ /// VPABSW ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Abs(Vector256<short> value) => Abs(value);
+ /// <summary>
+ /// __m256i _mm256_abs_epi32 (__m256i a)
+ /// VPABSD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Abs(Vector256<int> value) => Abs(value);
+
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Add(Vector256<sbyte> left, Vector256<sbyte> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Add(Vector256<byte> left, Vector256<byte> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Add(Vector256<short> left, Vector256<short> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Add(Vector256<ushort> left, Vector256<ushort> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Add(Vector256<int> left, Vector256<int> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Add(Vector256<uint> left, Vector256<uint> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Add(Vector256<long> left, Vector256<long> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Add(Vector256<ulong> left, Vector256<ulong> right) => Add(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_adds_epi8 (__m256i a, __m256i b)
+ /// VPADDSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AddSaturate(Vector256<sbyte> left, Vector256<sbyte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_adds_epu8 (__m256i a, __m256i b)
+ /// VPADDUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AddSaturate(Vector256<byte> left, Vector256<byte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_adds_epi16 (__m256i a, __m256i b)
+ /// VPADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AddSaturate(Vector256<short> left, Vector256<short> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_adds_epu16 (__m256i a, __m256i b)
+ /// VPADDUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AddSaturate(Vector256<ushort> left, Vector256<ushort> right) => AddSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_alignr_epi8 (__m256i a, __m256i b, const int count)
+ /// VPALIGNR ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> AlignRight(Vector256<sbyte> left, Vector256<sbyte> right, byte mask) => AlignRight(left, right, mask);
+
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> And(Vector256<sbyte> left, Vector256<sbyte> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> And(Vector256<byte> left, Vector256<byte> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> And(Vector256<short> left, Vector256<short> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> And(Vector256<ushort> left, Vector256<ushort> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> And(Vector256<int> left, Vector256<int> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> And(Vector256<uint> left, Vector256<uint> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> And(Vector256<long> left, Vector256<long> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> And(Vector256<ulong> left, Vector256<ulong> right) => And(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AndNot(Vector256<sbyte> left, Vector256<sbyte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AndNot(Vector256<byte> left, Vector256<byte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AndNot(Vector256<short> left, Vector256<short> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AndNot(Vector256<ushort> left, Vector256<ushort> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> AndNot(Vector256<int> left, Vector256<int> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> AndNot(Vector256<uint> left, Vector256<uint> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> AndNot(Vector256<long> left, Vector256<long> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> AndNot(Vector256<ulong> left, Vector256<ulong> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_avg_epu8 (__m256i a, __m256i b)
+ /// VPAVGB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Average(Vector256<byte> left, Vector256<byte> right) => Average(left, right);
+ /// <summary>
+ /// __m256i _mm256_avg_epu16 (__m256i a, __m256i b)
+ /// VPAVGW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Average(Vector256<ushort> left, Vector256<ushort> right) => Average(left, right);
+
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Blend(Vector128<int> left, Vector128<int> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Blend(Vector128<uint> left, Vector128<uint> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Blend(Vector256<short> left, Vector256<short> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Blend(Vector256<ushort> left, Vector256<ushort> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Blend(Vector256<int> left, Vector256<int> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Blend(Vector256<uint> left, Vector256<uint> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<sbyte> BlendVariable(Vector256<sbyte> left, Vector256<sbyte> right, Vector256<sbyte> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<byte> BlendVariable(Vector256<byte> left, Vector256<byte> right, Vector256<byte> mask) => BlendVariable(left, right, mask);
+
+ /// <summary>
+ /// __m128i _mm_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB xmm, xmm
+ /// __m128i _mm_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW xmm, xmm
+ /// __m128i _mm_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD xmm, xmm
+ /// __m128i _mm_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ xmm, xmm
+ /// __m128 _mm_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS xmm, xmm
+ /// __m128d _mm_broadcastsd_pd (__m128d a)
+ /// VMOVDDUP xmm, xmm
+ /// </summary>
+ public static Vector128<T> BroadcastScalarToVector128<T>(Vector128<T> value) where T : struct
+ {
+ return BroadcastScalarToVector128<T>(value);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB ymm, xmm
+ /// __m256i _mm256_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW ymm, xmm
+ /// __m256i _mm256_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD ymm, xmm
+ /// __m256i _mm256_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ ymm, xmm
+ /// __m256 _mm256_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS ymm, xmm
+ /// __m256d _mm256_broadcastsd_pd (__m128d a)
+ /// VBROADCASTSD ymm, xmm
+ /// </summary>
+ public static Vector256<T> BroadcastScalarToVector256<T>(Vector128<T> value) where T : struct
+ {
+ return BroadcastScalarToVector256<T>(value);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<sbyte> BroadcastVector128ToVector256(sbyte* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<byte> BroadcastVector128ToVector256(byte* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<short> BroadcastVector128ToVector256(short* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<ushort> BroadcastVector128ToVector256(ushort* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<int> BroadcastVector128ToVector256(int* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<uint> BroadcastVector128ToVector256(uint* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<long> BroadcastVector128ToVector256(long* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<ulong> BroadcastVector128ToVector256(ulong* address) => BroadcastVector128ToVector256(address);
+
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareEqual(Vector256<sbyte> left, Vector256<sbyte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> CompareEqual(Vector256<byte> left, Vector256<byte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareEqual(Vector256<short> left, Vector256<short> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> CompareEqual(Vector256<ushort> left, Vector256<ushort> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareEqual(Vector256<int> left, Vector256<int> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> CompareEqual(Vector256<uint> left, Vector256<uint> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareEqual(Vector256<long> left, Vector256<long> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> CompareEqual(Vector256<ulong> left, Vector256<ulong> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi8 (__m256i a, __m256i b)
+ /// VPCMPGTB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareGreaterThan(Vector256<sbyte> left, Vector256<sbyte> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi16 (__m256i a, __m256i b)
+ /// VPCMPGTW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareGreaterThan(Vector256<short> left, Vector256<short> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi32 (__m256i a, __m256i b)
+ /// VPCMPGTD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareGreaterThan(Vector256<int> left, Vector256<int> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi64 (__m256i a, __m256i b)
+ /// VPCMPGTQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareGreaterThan(Vector256<long> left, Vector256<long> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// double _mm256_cvtsd_f64 (__m256d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector256<double> value) => ConvertToDouble(value);
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector256<int> value) => ConvertToInt32(value);
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector256<uint> value) => ConvertToUInt32(value);
+
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi16 (__m128i a)
+ /// VPMOVSXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ConvertToVector256Int16(Vector128<sbyte> value) => ConvertToVector256Int16(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi16 (__m128i a)
+ /// VPMOVZXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ConvertToVector256UInt16(Vector128<byte> value) => ConvertToVector256UInt16(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi32 (__m128i a)
+ /// VPMOVSXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<sbyte> value) => ConvertToVector256Int32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi32 (__m128i a)
+ /// VPMOVSXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) => ConvertToVector256Int32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi32 (__m128i a)
+ /// VPMOVZXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<byte> value) => ConvertToVector256UInt32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi32 (__m128i a)
+ /// VPMOVZXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<ushort> value) => ConvertToVector256UInt32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi64 (__m128i a)
+ /// VPMOVSXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<sbyte> value) => ConvertToVector256Int64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi64 (__m128i a)
+ /// VPMOVSXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<short> value) => ConvertToVector256Int64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi32_epi64 (__m128i a)
+ /// VPMOVSXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<int> value) => ConvertToVector256Int64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi64 (__m128i a)
+ /// VPMOVZXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) => ConvertToVector256UInt64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi64 (__m128i a)
+ /// VPMOVZXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) => ConvertToVector256UInt64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu32_epi64 (__m128i a)
+ /// VPMOVZXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) => ConvertToVector256UInt64(value);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ExtractVector128(Vector256<sbyte> value, byte index) => ExtractVector128(value, index);
+ // <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<byte> ExtractVector128(Vector256<byte> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<short> ExtractVector128(Vector256<short> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ushort> ExtractVector128(Vector256<ushort> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<int> ExtractVector128(Vector256<int> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<uint> ExtractVector128(Vector256<uint> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<long> ExtractVector128(Vector256<long> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ulong> ExtractVector128(Vector256<ulong> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_i32gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_i64gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_i64gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherVector256(int* baseAddress, Vector256<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherVector256(uint* baseAddress, Vector256<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256 _mm256_i32gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherVector256(float* baseAddress, Vector256<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm256_i64gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_i64gather_pd (double const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPD ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<int> index, Vector128<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<int> index, Vector128<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<int> index, Vector128<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<int> index, Vector128<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_mask_i32gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<int> index, Vector128<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_mask_i32gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<int> index, Vector128<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<long> index, Vector128<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<long> index, Vector128<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<long> index, Vector128<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<long> index, Vector128<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_mask_i64gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<long> index, Vector128<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_mask_i64gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<long> index, Vector128<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherMaskVector256(Vector256<int> source, int* baseAddress, Vector256<int> index, Vector256<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherMaskVector256(Vector256<uint> source, uint* baseAddress, Vector256<int> index, Vector256<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector128<int> index, Vector256<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector128<int> index, Vector256<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256 _mm256_mask_i32gather_ps (__m256 src, float const* base_addr, __m256i vindex, __m256 mask, const int scale)
+ /// VPGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherMaskVector256(Vector256<float> source, float* baseAddress, Vector256<int> index, Vector256<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_mask_i32gather_pd (__m256d src, double const* base_addr, __m128i vindex, __m256d mask, const int scale)
+ /// VPGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector128<int> index, Vector256<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector256<long> index, Vector128<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector256<long> index, Vector128<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector256<long> index, Vector256<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector256<long> index, Vector256<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm256_mask_i64gather_ps (__m128 src, float const* base_addr, __m256i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector256<long> index, Vector128<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_mask_i64gather_pd (__m256d src, double const* base_addr, __m256i vindex, __m256d mask, const int scale)
+ /// VGATHERQPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector256<long> index, Vector256<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_hadd_epi16 (__m256i a, __m256i b)
+ /// VPHADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAdd(Vector256<short> left, Vector256<short> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m256i _mm256_hadd_epi32 (__m256i a, __m256i b)
+ /// VPHADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalAdd(Vector256<int> left, Vector256<int> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_hadds_epi16 (__m256i a, __m256i b)
+ /// VPHADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAddSaturate(Vector256<short> left, Vector256<short> right) => HorizontalAddSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_hsub_epi16 (__m256i a, __m256i b)
+ /// VPHSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtract(Vector256<short> left, Vector256<short> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_hsub_epi32 (__m256i a, __m256i b)
+ /// VPHSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalSubtract(Vector256<int> left, Vector256<int> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_hsubs_epi16 (__m256i a, __m256i b)
+ /// VPHSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtractSaturate(Vector256<short> left, Vector256<short> right) => HorizontalSubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<sbyte> InsertVector128(Vector256<sbyte> value, Vector128<sbyte> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xm128, imm8
+ /// </summary>
+ public new static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<byte> InsertVector128(Vector256<byte> value, Vector128<byte> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<short> InsertVector128(Vector256<short> value, Vector128<short> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ushort> InsertVector128(Vector256<ushort> value, Vector128<ushort> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<int> InsertVector128(Vector256<int> value, Vector128<int> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<uint> InsertVector128(Vector256<uint> value, Vector128<uint> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<long> InsertVector128(Vector256<long> value, Vector128<long> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ulong> InsertVector128(Vector256<ulong> value, Vector128<ulong> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256NonTemporal(sbyte* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256NonTemporal(byte* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256NonTemporal(short* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256NonTemporal(ushort* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256NonTemporal(int* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256NonTemporal(uint* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256NonTemporal(long* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256NonTemporal(ulong* address) => LoadAlignedVector256NonTemporal(address);
+
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> MaskLoad(int* address, Vector128<int> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> MaskLoad(uint* address, Vector128<uint> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> MaskLoad(long* address, Vector128<long> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> MaskLoad(ulong* address, Vector128<ulong> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> MaskLoad(int* address, Vector256<int> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> MaskLoad(uint* address, Vector256<uint> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> MaskLoad(long* address, Vector256<long> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> MaskLoad(ulong* address, Vector256<ulong> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector128<int> mask, Vector128<int> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector128<uint> mask, Vector128<uint> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector128<long> mask, Vector128<long> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector128<ulong> mask, Vector128<ulong> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector256<int> mask, Vector256<int> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector256<uint> mask, Vector256<uint> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector256<long> mask, Vector256<long> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector256<ulong> mask, Vector256<ulong> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// __m256i _mm256_madd_epi16 (__m256i a, __m256i b)
+ /// VPMADDWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyAddAdjacent(Vector256<short> left, Vector256<short> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_maddubs_epi16 (__m256i a, __m256i b)
+ /// VPMADDUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyAddAdjacent(Vector256<byte> left, Vector256<sbyte> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_max_epi8 (__m256i a, __m256i b)
+ /// VPMAXSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Max(Vector256<sbyte> left, Vector256<sbyte> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epu8 (__m256i a, __m256i b)
+ /// VPMAXUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Max(Vector256<byte> left, Vector256<byte> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epi16 (__m256i a, __m256i b)
+ /// VPMAXSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Max(Vector256<short> left, Vector256<short> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epu16 (__m256i a, __m256i b)
+ /// VPMAXUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Max(Vector256<ushort> left, Vector256<ushort> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epi32 (__m256i a, __m256i b)
+ /// VPMAXSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Max(Vector256<int> left, Vector256<int> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epu32 (__m256i a, __m256i b)
+ /// VPMAXUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Max(Vector256<uint> left, Vector256<uint> right) => Max(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_min_epi8 (__m256i a, __m256i b)
+ /// VPMINSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Min(Vector256<sbyte> left, Vector256<sbyte> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epu8 (__m256i a, __m256i b)
+ /// VPMINUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Min(Vector256<byte> left, Vector256<byte> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epi16 (__m256i a, __m256i b)
+ /// VPMINSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Min(Vector256<short> left, Vector256<short> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epu16 (__m256i a, __m256i b)
+ /// VPMINUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Min(Vector256<ushort> left, Vector256<ushort> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epi32 (__m256i a, __m256i b)
+ /// VPMINSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Min(Vector256<int> left, Vector256<int> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epu32 (__m256i a, __m256i b)
+ /// VPMINUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Min(Vector256<uint> left, Vector256<uint> right) => Min(left, right);
+
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<sbyte> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<byte> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m256i _mm256_mpsadbw_epu8 (__m256i a, __m256i b, const int imm8)
+ /// VMPSADBW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> MultipleSumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right, byte mask) => MultipleSumAbsoluteDifferences(left, right, mask);
+
+ /// <summary>
+ /// __m256i _mm256_mul_epi32 (__m256i a, __m256i b)
+ /// VPMULDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Multiply(Vector256<int> left, Vector256<int> right) => Multiply(left, right);
+ /// <summary>
+ /// __m256i _mm256_mul_epu32 (__m256i a, __m256i b)
+ /// VPMULUDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Multiply(Vector256<uint> left, Vector256<uint> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_mulhi_epi16 (__m256i a, __m256i b)
+ /// VPMULHW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHigh(Vector256<short> left, Vector256<short> right) => MultiplyHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_mulhi_epu16 (__m256i a, __m256i b)
+ /// VPMULHUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> MultiplyHigh(Vector256<ushort> left, Vector256<ushort> right) => MultiplyHigh(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_mulhrs_epi16 (__m256i a, __m256i b)
+ /// VPMULHRSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHighRoundScale(Vector256<short> left, Vector256<short> right) => MultiplyHighRoundScale(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_mullo_epi16 (__m256i a, __m256i b)
+ /// VPMULLW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyLow(Vector256<short> left, Vector256<short> right) => MultiplyLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_mullo_epi32 (__m256i a, __m256i b)
+ /// VPMULLD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyLow(Vector256<int> left, Vector256<int> right) => MultiplyLow(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Or(Vector256<sbyte> left, Vector256<sbyte> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Or(Vector256<byte> left, Vector256<byte> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Or(Vector256<short> left, Vector256<short> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Or(Vector256<ushort> left, Vector256<ushort> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Or(Vector256<int> left, Vector256<int> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Or(Vector256<uint> left, Vector256<uint> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Or(Vector256<long> left, Vector256<long> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Or(Vector256<ulong> left, Vector256<ulong> right) => Or(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_packs_epi16 (__m256i a, __m256i b)
+ /// VPACKSSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> PackSignedSaturate(Vector256<short> left, Vector256<short> right) => PackSignedSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_packs_epi32 (__m256i a, __m256i b)
+ /// VPACKSSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> PackSignedSaturate(Vector256<int> left, Vector256<int> right) => PackSignedSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_packus_epi16 (__m256i a, __m256i b)
+ /// VPACKUSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> PackUnsignedSaturate(Vector256<short> left, Vector256<short> right) => PackUnsignedSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_packus_epi32 (__m256i a, __m256i b)
+ /// VPACKUSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> PackUnsignedSaturate(Vector256<int> left, Vector256<int> right) => PackUnsignedSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> Permute2x128(Vector256<sbyte> left, Vector256<sbyte> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<byte> Permute2x128(Vector256<byte> left, Vector256<byte> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Permute2x128(Vector256<short> left, Vector256<short> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Permute2x128(Vector256<ushort> left, Vector256<ushort> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Permute2x128(Vector256<int> left, Vector256<int> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Permute2x128(Vector256<uint> left, Vector256<uint> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute2x128(Vector256<long> left, Vector256<long> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute2x128(Vector256<ulong> left, Vector256<ulong> right, byte control) => Permute2x128(left, right, control);
+
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute4x64(Vector256<long> value, byte control) => Permute4x64(value, control);
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute4x64(Vector256<ulong> value, byte control) => Permute4x64(value, control);
+ /// <summary>
+ /// __m256d _mm256_permute4x64_pd (__m256d a, const int imm8)
+ /// VPERMPD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Permute4x64(Vector256<double> value, byte control) => Permute4x64(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> PermuteVar8x32(Vector256<int> left, Vector256<int> control) => PermuteVar8x32(left, control);
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> PermuteVar8x32(Vector256<uint> left, Vector256<uint> control) => PermuteVar8x32(left, control);
+ /// <summary>
+ /// __m256 _mm256_permutevar8x32_ps (__m256 a, __m256i idx)
+ /// VPERMPS ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> PermuteVar8x32(Vector256<float> left, Vector256<int> control) => PermuteVar8x32(left, control);
+
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, Vector128<short> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, Vector128<ushort> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, Vector128<int> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, Vector128<uint> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, Vector128<long> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, Vector128<ulong> count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, byte count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftLeftLogical128BitLane(Vector256<sbyte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftLeftLogical128BitLane(Vector256<byte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical128BitLane(Vector256<short> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical128BitLane(Vector256<ushort> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical128BitLane(Vector256<int> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical128BitLane(Vector256<uint> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical128BitLane(Vector256<long> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical128BitLane(Vector256<ulong> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogicalVariable(Vector256<int> value, Vector256<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogicalVariable(Vector256<uint> value, Vector256<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogicalVariable(Vector256<long> value, Vector256<ulong> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) => ShiftLeftLogicalVariable(value, count);
+
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogicalVariable(Vector128<int> value, Vector128<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogicalVariable(Vector128<uint> value, Vector128<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogicalVariable(Vector128<long> value, Vector128<ulong> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) => ShiftLeftLogicalVariable(value, count);
+
+ /// <summary>
+ /// _mm256_sra_epi16 (__m256i a, __m128i count)
+ /// VPSRAW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, Vector128<short> count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// _mm256_sra_epi32 (__m256i a, __m128i count)
+ /// VPSRAD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, Vector128<int> count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srai_epi16 (__m256i a, int imm8)
+ /// VPSRAW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, byte count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// __m256i _mm256_srai_epi32 (__m256i a, int imm8)
+ /// VPSRAD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, byte count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srav_epi32 (__m256i a, __m256i count)
+ /// VPSRAVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmeticVariable(Vector256<int> value, Vector256<uint> count) => ShiftRightArithmeticVariable(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srav_epi32 (__m128i a, __m128i count)
+ /// VPSRAVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmeticVariable(Vector128<int> value, Vector128<uint> count) => ShiftRightArithmeticVariable(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, Vector128<short> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, Vector128<ushort> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, Vector128<int> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, Vector128<uint> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, Vector128<long> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, Vector128<ulong> count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, byte count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftRightLogical128BitLane(Vector256<sbyte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftRightLogical128BitLane(Vector256<byte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical128BitLane(Vector256<short> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical128BitLane(Vector256<ushort> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical128BitLane(Vector256<int> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical128BitLane(Vector256<uint> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical128BitLane(Vector256<long> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical128BitLane(Vector256<ulong> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightLogicalVariable(Vector256<int> value, Vector256<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogicalVariable(Vector256<uint> value, Vector256<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftRightLogicalVariable(Vector256<long> value, Vector256<ulong> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) => ShiftRightLogicalVariable(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogicalVariable(Vector128<int> value, Vector128<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogicalVariable(Vector128<uint> value, Vector128<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogicalVariable(Vector128<long> value, Vector128<ulong> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) => ShiftRightLogicalVariable(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Shuffle(Vector256<sbyte> value, Vector256<sbyte> mask) => Shuffle(value, mask);
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Shuffle(Vector256<byte> value, Vector256<byte> mask) => Shuffle(value, mask);
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Shuffle(Vector256<int> value, byte control) => Shuffle(value, control);
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Shuffle(Vector256<uint> value, byte control) => Shuffle(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleHigh(Vector256<short> value, byte control) => ShuffleHigh(value, control);
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleHigh(Vector256<ushort> value, byte control) => ShuffleHigh(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleLow(Vector256<short> value, byte control) => ShuffleLow(value, control);
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleLow(Vector256<ushort> value, byte control) => ShuffleLow(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_sign_epi8 (__m256i a, __m256i b)
+ /// VPSIGNB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Sign(Vector256<sbyte> left, Vector256<sbyte> right) => Sign(left, right);
+ /// <summary>
+ /// __m256i _mm256_sign_epi16 (__m256i a, __m256i b)
+ /// VPSIGNW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Sign(Vector256<short> left, Vector256<short> right) => Sign(left, right);
+ /// <summary>
+ /// __m256i _mm256_sign_epi32 (__m256i a, __m256i b)
+ /// VPSIGND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Sign(Vector256<int> left, Vector256<int> right) => Sign(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Subtract(Vector256<sbyte> left, Vector256<sbyte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Subtract(Vector256<byte> left, Vector256<byte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Subtract(Vector256<short> left, Vector256<short> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Subtract(Vector256<ushort> left, Vector256<ushort> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Subtract(Vector256<int> left, Vector256<int> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Subtract(Vector256<uint> left, Vector256<uint> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Subtract(Vector256<long> left, Vector256<long> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Subtract(Vector256<ulong> left, Vector256<ulong> right) => Subtract(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_subs_epi8 (__m256i a, __m256i b)
+ /// VPSUBSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> SubtractSaturate(Vector256<sbyte> left, Vector256<sbyte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_subs_epi16 (__m256i a, __m256i b)
+ /// VPSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> SubtractSaturate(Vector256<short> left, Vector256<short> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_subs_epu8 (__m256i a, __m256i b)
+ /// VPSUBUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> SubtractSaturate(Vector256<byte> left, Vector256<byte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_subs_epu16 (__m256i a, __m256i b)
+ /// VPSUBUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SubtractSaturate(Vector256<ushort> left, Vector256<ushort> right) => SubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_sad_epu8 (__m256i a, __m256i b)
+ /// VPSADBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right) => SumAbsoluteDifferences(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackHigh(Vector256<sbyte> left, Vector256<sbyte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackHigh(Vector256<byte> left, Vector256<byte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackHigh(Vector256<short> left, Vector256<short> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackHigh(Vector256<ushort> left, Vector256<ushort> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackHigh(Vector256<int> left, Vector256<int> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackHigh(Vector256<uint> left, Vector256<uint> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackHigh(Vector256<long> left, Vector256<long> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackHigh(Vector256<ulong> left, Vector256<ulong> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackLow(Vector256<sbyte> left, Vector256<sbyte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackLow(Vector256<byte> left, Vector256<byte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackLow(Vector256<short> left, Vector256<short> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackLow(Vector256<ushort> left, Vector256<ushort> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackLow(Vector256<int> left, Vector256<int> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackLow(Vector256<uint> left, Vector256<uint> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackLow(Vector256<long> left, Vector256<long> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackLow(Vector256<ulong> left, Vector256<ulong> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Xor(Vector256<sbyte> left, Vector256<sbyte> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Xor(Vector256<byte> left, Vector256<byte> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Xor(Vector256<short> left, Vector256<short> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Xor(Vector256<ushort> left, Vector256<ushort> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Xor(Vector256<int> left, Vector256<int> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Xor(Vector256<uint> left, Vector256<uint> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Xor(Vector256<long> left, Vector256<long> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Xor(Vector256<ulong> left, Vector256<ulong> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs
new file mode 100644
index 000000000..2b0b48fe7
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs
@@ -0,0 +1,96 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi1
+ {
+ internal Bmi1() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// unsigned int _andn_u32 (unsigned int a, unsigned int b)
+ /// ANDN r32a, r32b, reg/m32
+ /// </summary>
+ public static uint AndNot(uint left, uint right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _andn_u64 (unsigned __int64 a, unsigned __int64 b)
+ /// ANDN r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong AndNot(ulong left, ulong right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _bextr_u32 (unsigned int a, unsigned int start, unsigned int len)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, byte start, byte length) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _bextr_u64 (unsigned __int64 a, unsigned int start, unsigned int len)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, byte start, byte length) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned int _bextr2_u32 (unsigned int a, unsigned int control)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, ushort control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _bextr2_u64 (unsigned __int64 a, unsigned __int64 control)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, ushort control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _blsi_u32 (unsigned int a)
+ /// BLSI reg, reg/m32
+ /// </summary>
+ public static uint ExtractLowestSetBit(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _blsi_u64 (unsigned __int64 a)
+ /// BLSI reg, reg/m64
+ /// </summary>
+ public static ulong ExtractLowestSetBit(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _blsmsk_u32 (unsigned int a)
+ /// BLSMSK reg, reg/m32
+ /// </summary>
+ public static uint GetMaskUpToLowestSetBit(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _blsmsk_u64 (unsigned __int64 a)
+ /// BLSMSK reg, reg/m64
+ /// </summary>
+ public static ulong GetMaskUpToLowestSetBit(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _blsr_u32 (unsigned int a)
+ /// BLSR reg, reg/m32
+ /// </summary>
+ public static uint ResetLowestSetBit(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _blsr_u64 (unsigned __int64 a)
+ /// BLSR reg, reg/m64
+ /// </summary>
+ public static ulong ResetLowestSetBit(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_tzcnt_32 (unsigned int a)
+ /// TZCNT reg, reg/m32
+ /// </summary>
+ public static uint TrailingZeroCount(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_tzcnt_64 (unsigned __int64 a)
+ /// TZCNT reg, reg/m64
+ /// </summary>
+ public static ulong TrailingZeroCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs
new file mode 100644
index 000000000..f06f54d83
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs
@@ -0,0 +1,96 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi1
+ {
+ internal Bmi1() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// unsigned int _andn_u32 (unsigned int a, unsigned int b)
+ /// ANDN r32a, r32b, reg/m32
+ /// </summary>
+ public static uint AndNot(uint left, uint right) => AndNot(left, right);
+ /// <summary>
+ /// unsigned __int64 _andn_u64 (unsigned __int64 a, unsigned __int64 b)
+ /// ANDN r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong AndNot(ulong left, ulong right) => AndNot(left, right);
+
+ /// <summary>
+ /// unsigned int _bextr_u32 (unsigned int a, unsigned int start, unsigned int len)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, byte start, byte length) => BitFieldExtract(value, start, length);
+ /// <summary>
+ /// unsigned __int64 _bextr_u64 (unsigned __int64 a, unsigned int start, unsigned int len)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, byte start, byte length) => BitFieldExtract(value, start, length);
+ /// <summary>
+ /// unsigned int _bextr2_u32 (unsigned int a, unsigned int control)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, ushort control) => BitFieldExtract(value, control);
+ /// <summary>
+ /// unsigned __int64 _bextr2_u64 (unsigned __int64 a, unsigned __int64 control)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, ushort control) => BitFieldExtract(value, control);
+
+ /// <summary>
+ /// unsigned int _blsi_u32 (unsigned int a)
+ /// BLSI reg, reg/m32
+ /// </summary>
+ public static uint ExtractLowestSetBit(uint value) => ExtractLowestSetBit(value);
+ /// <summary>
+ /// unsigned __int64 _blsi_u64 (unsigned __int64 a)
+ /// BLSI reg, reg/m64
+ /// </summary>
+ public static ulong ExtractLowestSetBit(ulong value) => ExtractLowestSetBit(value);
+
+ /// <summary>
+ /// unsigned int _blsmsk_u32 (unsigned int a)
+ /// BLSMSK reg, reg/m32
+ /// </summary>
+ public static uint GetMaskUpToLowestSetBit(uint value) => GetMaskUpToLowestSetBit(value);
+ /// <summary>
+ /// unsigned __int64 _blsmsk_u64 (unsigned __int64 a)
+ /// BLSMSK reg, reg/m64
+ /// </summary>
+ public static ulong GetMaskUpToLowestSetBit(ulong value) => GetMaskUpToLowestSetBit(value);
+
+ /// <summary>
+ /// unsigned int _blsr_u32 (unsigned int a)
+ /// BLSR reg, reg/m32
+ /// </summary>
+ public static uint ResetLowestSetBit(uint value) => ResetLowestSetBit(value);
+ /// <summary>
+ /// unsigned __int64 _blsr_u64 (unsigned __int64 a)
+ /// BLSR reg, reg/m64
+ /// </summary>
+ public static ulong ResetLowestSetBit(ulong value) => ResetLowestSetBit(value);
+
+ /// <summary>
+ /// int _mm_tzcnt_32 (unsigned int a)
+ /// TZCNT reg, reg/m32
+ /// </summary>
+ public static uint TrailingZeroCount(uint value) => TrailingZeroCount(value);
+ /// <summary>
+ /// __int64 _mm_tzcnt_64 (unsigned __int64 a)
+ /// TZCNT reg, reg/m64
+ /// </summary>
+ public static ulong TrailingZeroCount(ulong value) => TrailingZeroCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs
new file mode 100644
index 000000000..0789d6f3c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs
@@ -0,0 +1,64 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi2
+ {
+ internal Bmi2() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// unsigned int _bzhi_u32 (unsigned int a, unsigned int index)
+ /// BZHI r32a, reg/m32, r32b
+ /// </summary>
+ public static uint ZeroHighBits(uint value, uint index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _bzhi_u64 (unsigned __int64 a, unsigned int index)
+ /// BZHI r64a, reg/m32, r64b
+ /// </summary>
+ public static ulong ZeroHighBits(ulong value, ulong index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
+ /// MULX r32a, r32b, reg/m32
+ /// </summary>
+ public static unsafe uint MultiplyNoFlags(uint left, uint right, uint* high) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
+ /// MULX r64a, r64b, reg/m64
+ /// </summary>
+ public static unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* high) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _pdep_u32 (unsigned int a, unsigned int mask)
+ /// PDEP r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitDeposit(uint value, uint mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _pdep_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PDEP r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitDeposit(ulong value, ulong mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _pext_u32 (unsigned int a, unsigned int mask)
+ /// PEXT r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitExtract(uint value, uint mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _pext_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PEXT r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitExtract(ulong value, ulong mask) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs
new file mode 100644
index 000000000..d8fb1521a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs
@@ -0,0 +1,64 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi2
+ {
+ internal Bmi2() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// unsigned int _bzhi_u32 (unsigned int a, unsigned int index)
+ /// BZHI r32a, reg/m32, r32b
+ /// </summary>
+ public static uint ZeroHighBits(uint value, uint index) => ZeroHighBits(value, index);
+ /// <summary>
+ /// unsigned __int64 _bzhi_u64 (unsigned __int64 a, unsigned int index)
+ /// BZHI r64a, reg/m32, r64b
+ /// </summary>
+ public static ulong ZeroHighBits(ulong value, ulong index) => ZeroHighBits(value, index);
+
+ /// <summary>
+ /// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
+ /// MULX r32a, r32b, reg/m32
+ /// </summary>
+ public static unsafe uint MultiplyNoFlags(uint left, uint right, uint* high) => MultiplyNoFlags(left, right, high);
+ /// <summary>
+ /// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
+ /// MULX r64a, r64b, reg/m64
+ /// </summary>
+ public static unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* high) => MultiplyNoFlags(left, right, high);
+
+ /// <summary>
+ /// unsigned int _pdep_u32 (unsigned int a, unsigned int mask)
+ /// PDEP r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitDeposit(uint value, uint mask) => ParallelBitDeposit(value, mask);
+ /// <summary>
+ /// unsigned __int64 _pdep_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PDEP r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitDeposit(ulong value, ulong mask) => ParallelBitDeposit(value, mask);
+
+ /// <summary>
+ /// unsigned int _pext_u32 (unsigned int a, unsigned int mask)
+ /// PEXT r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitExtract(uint value, uint mask) => ParallelBitExtract(value, mask);
+ /// <summary>
+ /// unsigned __int64 _pext_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PEXT r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitExtract(ulong value, ulong mask) => ParallelBitExtract(value, mask);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs
new file mode 100644
index 000000000..cf8cd4370
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs
@@ -0,0 +1,189 @@
+// 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.
+
+namespace System.Runtime.Intrinsics.X86
+{
+ public enum FloatComparisonMode : byte
+ {
+ /// <summary>
+ /// _CMP_EQ_OQ
+ /// </summary>
+ EqualOrderedNonSignaling = 0,
+
+ /// <summary>
+ /// _CMP_LT_OS
+ /// </summary>
+ LessThanOrderedSignaling = 1,
+
+ /// <summary>
+ /// _CMP_LE_OS
+ /// </summary>
+ LessThanOrEqualOrderedSignaling = 2,
+
+ /// <summary>
+ /// _CMP_UNORD_Q
+ /// </summary>
+ UnorderedNonSignaling = 3,
+
+ /// <summary>
+ /// _CMP_NEQ_UQ
+ /// </summary>
+ NotEqualUnorderedNonSignaling = 4,
+
+ /// <summary>
+ /// _CMP_NLT_US
+ /// </summary>
+ NotLessThanUnorderedSignaling = 5,
+
+ /// <summary>
+ /// _CMP_NLE_US
+ /// </summary>
+ NotLessThanOrEqualUnorderedSignaling = 6,
+
+ /// <summary>
+ /// _CMP_ORD_Q
+ /// </summary>
+ OrderedNonSignaling = 7,
+
+ /// <summary>
+ /// _CMP_EQ_UQ
+ /// </summary>
+ EqualUnorderedNonSignaling = 8,
+
+ /// <summary>
+ /// _CMP_NGE_US
+ /// </summary>
+ NotGreaterThanOrEqualUnorderedSignaling = 9,
+
+ /// <summary>
+ /// _CMP_NGT_US
+ /// </summary>
+ NotGreaterThanUnorderedSignaling = 10,
+
+ /// <summary>
+ /// _CMP_FALSE_OQ
+ /// </summary>
+ FalseOrderedNonSignaling = 11,
+
+ /// <summary>
+ /// _CMP_NEQ_OQ
+ /// </summary>
+ NotEqualOrderedNonSignaling = 12,
+
+ /// <summary>
+ /// _CMP_GE_OS
+ /// </summary>
+ GreaterThanOrEqualOrderedSignaling = 13,
+
+ /// <summary>
+ /// _CMP_GT_OS
+ /// </summary>
+ GreaterThanOrderedSignaling = 14,
+
+ /// <summary>
+ /// _CMP_TRUE_UQ
+ /// </summary>
+ TrueUnorderedNonSignaling = 15,
+
+ /// <summary>
+ /// _CMP_EQ_OS
+ /// </summary>
+ EqualOrderedSignaling = 16,
+
+ /// <summary>
+ /// _CMP_LT_OQ
+ /// </summary>
+ LessThanOrderedNonSignaling = 17,
+
+ /// <summary>
+ /// _CMP_LE_OQ
+ /// </summary>
+ LessThanOrEqualOrderedNonSignaling = 18,
+
+ /// <summary>
+ /// _CMP_UNORD_S
+ /// </summary>
+ UnorderedSignaling = 19,
+
+ /// <summary>
+ /// _CMP_NEQ_US
+ /// </summary>
+ NotEqualUnorderedSignaling = 20,
+
+ /// <summary>
+ /// _CMP_NLT_UQ
+ /// </summary>
+ NotLessThanUnorderedNonSignaling = 21,
+
+ /// <summary>
+ /// _CMP_NLE_UQ
+ /// </summary>
+ NotLessThanOrEqualUnorderedNonSignaling = 22,
+
+ /// <summary>
+ /// _CMP_ORD_S
+ /// </summary>
+ OrderedSignaling = 23,
+
+ /// <summary>
+ /// _CMP_EQ_US
+ /// </summary>
+ EqualUnorderedSignaling = 24,
+
+ /// <summary>
+ /// _CMP_NGE_UQ
+ /// </summary>
+ NotGreaterThanOrEqualUnorderedNonSignaling = 25,
+
+ /// <summary>
+ /// _CMP_NGT_UQ
+ /// </summary>
+ NotGreaterThanUnorderedNonSignaling = 26,
+
+ /// <summary>
+ /// _CMP_FALSE_OS
+ /// </summary>
+ FalseOrderedSignaling = 27,
+
+ /// <summary>
+ /// _CMP_NEQ_OS
+ /// </summary>
+ NotEqualOrderedSignaling = 28,
+
+ /// <summary>
+ /// _CMP_GE_OQ
+ /// </summary>
+ GreaterThanOrEqualOrderedNonSignaling = 29,
+
+ /// <summary>
+ /// _CMP_GT_OQ
+ /// </summary>
+ GreaterThanOrderedNonSignaling = 30,
+
+ /// <summary>
+ /// _CMP_TRUE_US
+ /// </summary>
+ TrueUnorderedSignaling = 31,
+ }
+
+ public enum StringComparisonMode : byte {
+ EqualAny = 0x00,
+ Ranges = 0x04,
+ EqualEach = 0x08,
+ EqualOrdered = 0x0c,
+ NegativePolarity = 0x10,
+ MaskedNegativePolarity = 0x30,
+ LeastSignificant = 0x00,
+ MostSignificant = 0x40,
+ }
+
+
+ public enum ResultsFlag : byte {
+ CFlag = 0,
+ NotCFlagAndNotZFlag = 1,
+ OFlag = 2,
+ SFlag = 3,
+ ZFlag = 4,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs
new file mode 100644
index 000000000..91becab4d
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs
@@ -0,0 +1,190 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel FMA hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Fma : Avx
+ {
+ internal Fma() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSS xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmaddsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddSubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmaddsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddSubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmaddsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddSubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmaddsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddSubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmsubadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmsubadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmsubadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmsubadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fnmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fnmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fnmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fnmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs
new file mode 100644
index 000000000..88cb8d0cb
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs
@@ -0,0 +1,190 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel FMA hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Fma : Avx
+ {
+ internal Fma() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAdd(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAdd(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplyAdd(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplyAdd(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSS xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddScalar(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmaddsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddSubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddSubtract(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmaddsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddSubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddSubtract(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmaddsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddSubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplyAddSubtract(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmaddsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddSubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplyAddSubtract(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtract(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtract(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplySubtract(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplySubtract(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractScalar(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmsubadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractAdd(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmsubadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractAdd(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmsubadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplySubtractAdd(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmsubadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplySubtractAdd(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddNegated(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddNegated(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fnmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplyAddNegated(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fnmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplyAddNegated(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddNegatedScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddNegatedScalar(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractNegated(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractNegated(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fnmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplySubtractNegated(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fnmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplySubtractNegated(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractNegatedScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractNegatedScalar(a, b, c);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs
new file mode 100644
index 000000000..4f9276216
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs
@@ -0,0 +1,30 @@
+// 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;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel LZCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Lzcnt
+ {
+ internal Lzcnt() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// unsigned int _lzcnt_u32 (unsigned int a)
+ /// LZCNT reg, reg/m32
+ /// </summary>
+ public static uint LeadingZeroCount(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _lzcnt_u64 (unsigned __int64 a)
+ /// LZCNT reg, reg/m64
+ /// </summary>
+ public static ulong LeadingZeroCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs
new file mode 100644
index 000000000..5e9594f7d
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs
@@ -0,0 +1,31 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel LZCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Lzcnt
+ {
+ internal Lzcnt() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// unsigned int _lzcnt_u32 (unsigned int a)
+ /// LZCNT reg, reg/m32
+ /// </summary>
+ public static uint LeadingZeroCount(uint value) => LeadingZeroCount(value);
+ /// <summary>
+ /// unsigned __int64 _lzcnt_u64 (unsigned __int64 a)
+ /// LZCNT reg, reg/m64
+ /// </summary>
+ public static ulong LeadingZeroCount(ulong value) => LeadingZeroCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs
new file mode 100644
index 000000000..b79e50a2b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs
@@ -0,0 +1,31 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel PCLMULQDQ hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Pclmulqdq : Sse2
+ {
+ internal Pclmulqdq() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<long> CarrylessMultiply(Vector128<long> left, Vector128<long> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ulong> CarrylessMultiply(Vector128<ulong> left, Vector128<ulong> right, byte control) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs
new file mode 100644
index 000000000..c108e65f0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs
@@ -0,0 +1,31 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel PCLMULQDQ hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Pclmulqdq : Sse2
+ {
+ internal Pclmulqdq() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<long> CarrylessMultiply(Vector128<long> left, Vector128<long> right, byte control) => CarrylessMultiply(left, right, control);
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ulong> CarrylessMultiply(Vector128<ulong> left, Vector128<ulong> right, byte control) => CarrylessMultiply(left, right, control);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs
new file mode 100644
index 000000000..bf045bd1f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs
@@ -0,0 +1,30 @@
+// 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;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel POPCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Popcnt : Sse42
+ {
+ internal Popcnt() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// int _mm_popcnt_u32 (unsigned int a)
+ /// POPCNT reg, reg/m32
+ /// </summary>
+ public static uint PopCount(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_popcnt_u64 (unsigned __int64 a)
+ /// POPCNT reg64, reg/m64
+ /// </summary>
+ public static ulong PopCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs
new file mode 100644
index 000000000..ba73eb234
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs
@@ -0,0 +1,31 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel POPCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Popcnt : Sse42
+ {
+ internal Popcnt() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// int _mm_popcnt_u32 (unsigned int a)
+ /// POPCNT reg, reg/m32
+ /// </summary>
+ public static uint PopCount(uint value) => PopCount(value);
+ /// <summary>
+ /// __int64 _mm_popcnt_u64 (unsigned __int64 a)
+ /// POPCNT reg, reg/m64
+ /// </summary>
+ public static ulong PopCount(ulong value) => PopCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs
new file mode 100644
index 000000000..77c63cee3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs
@@ -0,0 +1,606 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse
+ {
+ internal Sse() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128 _mm_add_ps (__m128 a, __m128 b)
+ /// ADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Add(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_add_ss (__m128 a, __m128 b)
+ /// ADDSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> AddScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_and_ps (__m128 a, __m128 b)
+ /// ANDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> And(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_andnot_ps (__m128 a, __m128 b)
+ /// ANDNPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AndNot(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comieq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomieq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comigt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomigt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comige_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomige_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ss (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comilt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomilt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmple_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comile_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomile_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmple_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comineq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomineq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrdered(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnordered(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cvtss_si32 (__m128 a)
+ /// CVTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtss_si64 (__m128 a)
+ /// CVTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float _mm_cvtss_f32 (__m128 a)
+ /// HELPER: MOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cvtsi32_ss (__m128 a, int b)
+ /// CVTSI2SS xmm, reg/m32
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtsi64_ss (__m128 a, __int64 b)
+ /// CVTSI2SS xmm, reg/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, long value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cvttss_si32 (__m128 a)
+ /// CVTTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvttss_si64 (__m128 a)
+ /// CVTTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_div_ps (__m128 a, __m128 b)
+ /// DIVPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_div_ss (__m128 a, __m128 b)
+ /// DIVSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> DivideScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_loadu_ps (float const* mem_address)
+ /// MOVUPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadVector128(float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_load_ss (float const* mem_address)
+ /// MOVSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> LoadScalarVector128(float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_load_ps (float const* mem_address)
+ /// MOVAPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadAlignedVector128(float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_loadh_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVHPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadHigh(Vector128<float> lower, float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_loadl_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVLPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadLow(Vector128<float> upper, float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_max_ps (__m128 a, __m128 b)
+ /// MAXPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_max_ss (__m128 a, __m128 b)
+ /// MAXSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MaxScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_min_ps (__m128 a, __m128 b)
+ /// MINPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_min_ss (__m128 a, __m128 b)
+ /// MINSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MinScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_move_ss (__m128 a, __m128 b)
+ /// MOVSS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_movehl_ps (__m128 a, __m128 b)
+ /// MOVHLPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveHighToLow(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_movelh_ps (__m128 a, __m128 b)
+ /// MOVLHPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveLowToHigh(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_movemask_ps (__m128 a)
+ /// MOVMSKPS reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_mul_ps (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_mul_ss (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT0 m8
+ /// </summary>
+ public static unsafe void Prefetch0(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT1 m8
+ /// </summary>
+ public static unsafe void Prefetch1(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT2 m8
+ /// </summary>
+ public static unsafe void Prefetch2(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHNTA m8
+ /// </summary>
+ public static unsafe void PrefetchNonTemporal(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_or_ps (__m128 a, __m128 b)
+ /// ORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Or(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rcp_ps (__m128 a)
+ /// RCPPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Reciprocal(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a)
+ /// RCPSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a, __m128 b)
+ /// RCPSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ps (__m128 a)
+ /// RSQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a)
+ /// RSQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a, __m128 b)
+ /// RSQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_set_ps (float e3, float e2, float e1, float e0)
+ /// </summary>
+ public static Vector128<float> SetVector128(float e3, float e2, float e1, float e0) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_set_ss (float a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<float> SetScalarVector128(float value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_set1_ps (float a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<float> SetAllVector128(float value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_setzero_ps (void)
+ /// HELPER - XORPS
+ /// </summary>
+ public static Vector128<float> SetZeroVector128() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_castpd_ps (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castpd_si128 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castps_pd (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castps_si128 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castsi128_pd (__m128i a)
+ /// HELPER - No Codegen
+ /// __m128 _mm_castsi128_ps (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<U> StaticCast<T, U>(Vector128<T> value) where T : struct where U : struct { throw new PlatformNotSupportedException(); }
+
+
+ /// <summary>
+ /// __m128 _mm_shuffle_ps (__m128 a, __m128 b, unsigned int control)
+ /// SHUFPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Shuffle(Vector128<float> left, Vector128<float> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ps (__m128 a)
+ /// SQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Sqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a)
+ /// SQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a, __m128 b)
+ /// SQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_ps (float* mem_addr, __m128 a)
+ /// MOVAPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_ps (float* mem_addr, __m128 a)
+ /// MOVNTPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeu_ps (float* mem_addr, __m128 a)
+ /// MOVUPS m128, xmm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_sfence(void)
+ /// SFENCE
+ /// </summary>
+ public static void StoreFence() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_ss (float* mem_addr, __m128 a)
+ /// MOVSS m32, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeh_pi (__m64* mem_addr, __m128 a)
+ /// MOVHPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storel_pi (__m64* mem_addr, __m128 a)
+ /// MOVLPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sub_ps (__m128d a, __m128d b)
+ /// SUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Subtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sub_ss (__m128 a, __m128 b)
+ /// SUBSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SubtractScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_unpackhi_ps (__m128 a, __m128 b)
+ /// UNPCKHPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackHigh(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_unpacklo_ps (__m128 a, __m128 b)
+ /// UNPCKLPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackLow(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_xor_ps (__m128 a, __m128 b)
+ /// XORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Xor(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs
new file mode 100644
index 000000000..3b01aee70
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs
@@ -0,0 +1,631 @@
+// 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.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse
+ {
+ internal Sse() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128 _mm_add_ps (__m128 a, __m128 b)
+ /// ADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Add(Vector128<float> left, Vector128<float> right) => Add(left, right);
+
+ /// <summary>
+ /// __m128 _mm_add_ss (__m128 a, __m128 b)
+ /// ADDSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> AddScalar(Vector128<float> left, Vector128<float> right) => AddScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_and_ps (__m128 a, __m128 b)
+ /// ANDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> And(Vector128<float> left, Vector128<float> right) => And(left, right);
+
+ /// <summary>
+ /// __m128 _mm_andnot_ps (__m128 a, __m128 b)
+ /// ANDNPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AndNot(Vector128<float> left, Vector128<float> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqual(Vector128<float> left, Vector128<float> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comieq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomieq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqualScalar(Vector128<float> left, Vector128<float> right) => CompareEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThan(Vector128<float> left, Vector128<float> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// int _mm_comigt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomigt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comige_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomige_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ss (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThan(Vector128<float> left, Vector128<float> right) => CompareLessThan(left, right);
+
+ /// <summary>
+ /// int _mm_comilt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomilt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThanScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmple_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comile_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomile_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmple_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqual(Vector128<float> left, Vector128<float> right) => CompareNotEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comineq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomineq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThan(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThan(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanScalar(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThan(Vector128<float> left, Vector128<float> right) => CompareNotLessThan(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanScalar(Vector128<float> left, Vector128<float> right) => CompareNotLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareNotLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrdered(Vector128<float> left, Vector128<float> right) => CompareOrdered(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareOrderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnordered(Vector128<float> left, Vector128<float> right) => CompareUnordered(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareUnorderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_cvtss_si32 (__m128 a)
+ /// CVTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32(Vector128<float> value) => ConvertToInt32(value);
+ /// <summary>
+ /// __int64 _mm_cvtss_si64 (__m128 a)
+ /// CVTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64(Vector128<float> value) => ConvertToInt64(value);
+
+ /// <summary>
+ /// float _mm_cvtss_f32 (__m128 a)
+ /// HELPER: MOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector128<float> value) => ConvertToSingle(value);
+
+ /// <summary>
+ /// __m128 _mm_cvtsi32_ss (__m128 a, int b)
+ /// CVTSI2SS xmm, reg/m32
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, int value) => ConvertScalarToVector128Single(upper, value);
+ /// <summary>
+ /// __m128 _mm_cvtsi64_ss (__m128 a, __int64 b)
+ /// CVTSI2SS xmm, reg/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, long value) => ConvertScalarToVector128Single(upper, value);
+
+ /// <summary>
+ /// int _mm_cvttss_si32 (__m128 a)
+ /// CVTTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<float> value) => ConvertToInt32WithTruncation(value);
+ /// <summary>
+ /// __int64 _mm_cvttss_si64 (__m128 a)
+ /// CVTTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<float> value) => ConvertToInt64WithTruncation(value);
+
+ /// <summary>
+ /// __m128 _mm_div_ps (__m128 a, __m128 b)
+ /// DIVPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) => Divide(left, right);
+
+ /// <summary>
+ /// __m128 _mm_div_ss (__m128 a, __m128 b)
+ /// DIVSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> DivideScalar(Vector128<float> left, Vector128<float> right) => DivideScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_loadu_ps (float const* mem_address)
+ /// MOVUPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadVector128(float* address) => LoadVector128(address);
+
+ /// <summary>
+ /// __m128 _mm_load_ss (float const* mem_address)
+ /// MOVSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> LoadScalarVector128(float* address) => LoadScalarVector128(address);
+
+ /// <summary>
+ /// __m128 _mm_load_ps (float const* mem_address)
+ /// MOVAPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadAlignedVector128(float* address) => LoadAlignedVector128(address);
+
+ /// <summary>
+ /// __m128 _mm_loadh_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVHPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadHigh(Vector128<float> lower, float* address) => LoadHigh(lower, address);
+
+ /// <summary>
+ /// __m128 _mm_loadl_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVLPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadLow(Vector128<float> upper, float* address) => LoadLow(upper, address);
+
+ /// <summary>
+ /// __m128 _mm_max_ps (__m128 a, __m128 b)
+ /// MAXPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) => Max(left, right);
+
+ /// <summary>
+ /// __m128 _mm_max_ss (__m128 a, __m128 b)
+ /// MAXSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MaxScalar(Vector128<float> left, Vector128<float> right) => MaxScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_min_ps (__m128 a, __m128 b)
+ /// MINPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) => Min(left, right);
+
+ /// <summary>
+ /// __m128 _mm_min_ss (__m128 a, __m128 b)
+ /// MINSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MinScalar(Vector128<float> left, Vector128<float> right) => MinScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_move_ss (__m128 a, __m128 b)
+ /// MOVSS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveScalar(Vector128<float> upper, Vector128<float> value) => MoveScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_movehl_ps (__m128 a, __m128 b)
+ /// MOVHLPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveHighToLow(Vector128<float> left, Vector128<float> right) => MoveHighToLow(left, right);
+
+ /// <summary>
+ /// __m128 _mm_movelh_ps (__m128 a, __m128 b)
+ /// MOVLHPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveLowToHigh(Vector128<float> left, Vector128<float> right) => MoveLowToHigh(left, right);
+
+ /// <summary>
+ /// int _mm_movemask_ps (__m128 a)
+ /// MOVMSKPS reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<float> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m128 _mm_mul_ps (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m128 _mm_mul_ss (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyScalar(Vector128<float> left, Vector128<float> right) => MultiplyScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_or_ps (__m128 a, __m128 b)
+ /// ORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Or(Vector128<float> left, Vector128<float> right) => Or(left, right);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT0 m8
+ /// </summary>
+ public static unsafe void Prefetch0(void* address) => Prefetch0(address);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT1 m8
+ /// </summary>
+ public static unsafe void Prefetch1(void* address) => Prefetch1(address);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT2 m8
+ /// </summary>
+ public static unsafe void Prefetch2(void* address) => Prefetch2(address);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHNTA m8
+ /// </summary>
+ public static unsafe void PrefetchNonTemporal(void* address) => PrefetchNonTemporal(address);
+
+ /// <summary>
+ /// __m128 _mm_rcp_ps (__m128 a)
+ /// RCPPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Reciprocal(Vector128<float> value) => Reciprocal(value);
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a)
+ /// RCPSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> value) => ReciprocalScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a, __m128 b)
+ /// RCPSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> upper, Vector128<float> value) => ReciprocalScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ps (__m128 a)
+ /// RSQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrt(Vector128<float> value) => ReciprocalSqrt(value);
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a)
+ /// RSQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> value) => ReciprocalSqrtScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a, __m128 b)
+ /// RSQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> upper, Vector128<float> value) => ReciprocalSqrtScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_set1_ps (float a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> SetAllVector128(float value)
+ {
+ // Zero vector and load value et index 0
+ Vector128<float> vector = SetScalarVector128(value);
+ // Create { vl vl vl vl } and return result
+ return Shuffle(vector, vector, 0);
+ }
+
+ /// <summary>
+ /// __m128 _mm_set_ss (float a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<float> SetScalarVector128(float value) => SetScalarVector128(value);
+
+ /// <summary>
+ /// __m128 _mm_set_ps (float e3, float e2, float e1, float e0)
+ /// </summary>
+ public static unsafe Vector128<float> SetVector128(float e3, float e2, float e1, float e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e2 et index 0
+ Vector128<float> e2Vector = SetScalarVector128(e2);
+ Vector128<float> e1Vector = SetScalarVector128(e1);
+ Vector128<float> e0Vector = SetScalarVector128(e0);
+ // Create { -- -- e2 e0 }
+ e0Vector = UnpackLow(e0Vector, e2Vector);
+ e2Vector = SetScalarVector128(e3);
+ // Create { -- -- e3 e1 }
+ e1Vector = UnpackLow(e1Vector, e2Vector);
+ // Create { e3 e2 e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+
+ /// <summary>
+ /// __m128d _mm_setzero_ps (void)
+ /// HELPER - XORPS
+ /// </summary>
+ public static Vector128<float> SetZeroVector128() => SetZeroVector128();
+
+ /// <summary>
+ /// __m128 _mm_castpd_ps (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castpd_si128 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castps_pd (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castps_si128 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castsi128_pd (__m128i a)
+ /// HELPER - No Codegen
+ /// __m128 _mm_castsi128_ps (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<U> StaticCast<T, U>(Vector128<T> value) where T : struct where U : struct
+ {
+ return StaticCast<T, U>(value);
+ }
+
+ /// <summary>
+ /// __m128 _mm_shuffle_ps (__m128 a, __m128 b, unsigned int control)
+ /// SHUFPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Shuffle(Vector128<float> left, Vector128<float> right, byte control) => Shuffle(left, right, control);
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ps (__m128 a)
+ /// SQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Sqrt(Vector128<float> value) => Sqrt(value);
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a)
+ /// SQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> value) => SqrtScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a, __m128 b)
+ /// SQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> upper, Vector128<float> value) => SqrtScalar(upper, value);
+
+ /// <summary>
+ /// void _mm_store_ps (float* mem_addr, __m128 a)
+ /// MOVAPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector128<float> source) => StoreAligned(address, source);
+
+ /// <summary>
+ /// void _mm_stream_ps (float* mem_addr, __m128 a)
+ /// MOVNTPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector128<float> source) => StoreAlignedNonTemporal(address, source);
+
+ /// <summary>
+ /// void _mm_storeu_ps (float* mem_addr, __m128 a)
+ /// MOVUPS m128, xmm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector128<float> source) => Store(address, source);
+
+ /// <summary>
+ /// void _mm_sfence(void)
+ /// SFENCE
+ /// </summary>
+ public static void StoreFence() => StoreFence();
+
+ /// <summary>
+ /// void _mm_store_ss (float* mem_addr, __m128 a)
+ /// MOVSS m32, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(float* address, Vector128<float> source) => StoreScalar(address, source);
+
+ /// <summary>
+ /// void _mm_storeh_pi (__m64* mem_addr, __m128 a)
+ /// MOVHPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(float* address, Vector128<float> source) => StoreHigh(address, source);
+
+ /// <summary>
+ /// void _mm_storel_pi (__m64* mem_addr, __m128 a)
+ /// MOVLPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(float* address, Vector128<float> source) => StoreLow(address, source);
+
+ /// <summary>
+ /// __m128d _mm_sub_ps (__m128d a, __m128d b)
+ /// SUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Subtract(Vector128<float> left, Vector128<float> right) => Subtract(left, right);
+
+ /// <summary>
+ /// __m128 _mm_sub_ss (__m128 a, __m128 b)
+ /// SUBSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SubtractScalar(Vector128<float> left, Vector128<float> right) => SubtractScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_unpackhi_ps (__m128 a, __m128 b)
+ /// UNPCKHPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackHigh(Vector128<float> left, Vector128<float> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m128 _mm_unpacklo_ps (__m128 a, __m128 b)
+ /// UNPCKLPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackLow(Vector128<float> left, Vector128<float> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m128 _mm_xor_ps (__m128 a, __m128 b)
+ /// XORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Xor(Vector128<float> left, Vector128<float> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs
new file mode 100644
index 000000000..0f9b1959b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs
@@ -0,0 +1,1763 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse2 : Sse
+ {
+ internal Sse2() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Add(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Add(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Add(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Add(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Add(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Add(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Add(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Add(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_add_pd (__m128d a, __m128d b)
+ /// ADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Add(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_add_sd (__m128d a, __m128d b)
+ /// ADDSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> AddScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_adds_epi8 (__m128i a, __m128i b)
+ /// PADDSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_adds_epu8 (__m128i a, __m128i b)
+ /// PADDUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_adds_epi16 (__m128i a, __m128i b)
+ /// PADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_adds_epu16 (__m128i a, __m128i b)
+ /// PADDUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> And(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> And(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> And(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> And(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> And(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> And(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> And(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> And(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_and_pd (__m128d a, __m128d b)
+ /// ANDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> And(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AndNot(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AndNot(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AndNot(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AndNot(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> AndNot(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> AndNot(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> AndNot(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> AndNot(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_andnot_pd (__m128d a, __m128d b)
+ /// ADDNPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AndNot(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_avg_epu8 (__m128i a, __m128i b)
+ /// PAVGB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Average(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_avg_epu16 (__m128i a, __m128i b)
+ /// PAVGW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Average(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareEqual(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> CompareEqual(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareEqual(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> CompareEqual(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareEqual(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> CompareEqual(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmpeq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comieq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomieq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareGreaterThan(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareGreaterThan(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareGreaterThan(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmpgt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comigt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomigt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comige_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomige_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareLessThan(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmplt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareLessThan(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmplt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareLessThan(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmplt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comilt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomilt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmplt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmple_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comile_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomile_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmple_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comineq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomineq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrdered(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnordered(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cvtps_epi32 (__m128 a)
+ /// CVTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtpd_epi32 (__m128d a)
+ /// CVTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtepi32_ps (__m128i a)
+ /// CVTDQ2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtpd_ps (__m128d a)
+ /// CVTPD2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtepi32_pd (__m128i a)
+ /// CVTDQ2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtps_pd (__m128 a)
+ /// CVTPS2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// double _mm_cvtsd_f64(__m128d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_cvtsd_si32 (__m128d a)
+ /// CVTSD2SI r32, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtsd_si64 (__m128d a)
+ /// CVTSD2SI r64, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static long ConvertToInt64(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static ulong ConvertToUInt64(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cvtsi32_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtsi64_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtss_sd (__m128d a, __m128 b)
+ /// CVTSS2SD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<int> ConvertScalarToVector128Int32(int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<long> ConvertScalarToVector128Int64(long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtsd_ss (__m128 a, __m128d b)
+ /// CVTSD2SS xmm, xmm/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<uint> ConvertScalarToVector128UInt32(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<ulong> ConvertScalarToVector128UInt64(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cvttps_epi32 (__m128 a)
+ /// CVTTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvttpd_epi32 (__m128d a)
+ /// CVTTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cvttsd_si32 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvttsd_si64 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_div_pd (__m128d a, __m128d b)
+ /// DIVPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_div_sd (__m128d a, __m128d b)
+ /// DIVSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> DivideScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_extract_epi16 (__m128i a, int immediate)
+ /// PEXTRW reg, xmm, imm8
+ /// </summary>
+ public static ushort Extract(Vector128<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<short> Insert(Vector128<short> value, short data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<ushort> Insert(Vector128<ushort> value, ushort data, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadVector128(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadVector128(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadVector128(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadVector128(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadVector128(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadVector128(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_loadu_pd (double const* mem_address)
+ /// MOVUPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_load_sd (double const* mem_address)
+ /// MOVSD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadScalarVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_load_pd (double const* mem_address)
+ /// MOVAPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadAlignedVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_lfence(void)
+ /// LFENCE
+ /// </summary>
+ public static void LoadFence() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_loadh_pd (__m128d a, double const* mem_addr)
+ /// MOVHPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadHigh(Vector128<double> lower, double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_loadl_pd (__m128d a, double const* mem_addr)
+ /// MOVLPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadLow(Vector128<double> upper, double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m64
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<int> LoadScalarVector128(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m64
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<uint> LoadScalarVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<long> LoadScalarVector128(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadScalarVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<sbyte> source, Vector128<sbyte> mask, sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<byte> source, Vector128<byte> mask, byte* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_max_epu8 (__m128i a, __m128i b)
+ /// PMAXUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epi16 (__m128i a, __m128i b)
+ /// PMAXSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_max_pd (__m128d a, __m128d b)
+ /// MAXPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_max_sd (__m128d a, __m128d b)
+ /// MAXSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MaxScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_mfence(void)
+ /// MFENCE
+ /// </summary>
+ public static void MemoryFence() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_min_epu8 (__m128i a, __m128i b)
+ /// PMINUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epi16 (__m128i a, __m128i b)
+ /// PMINSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_min_pd (__m128d a, __m128d b)
+ /// MINPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_min_sd (__m128d a, __m128d b)
+ /// MINSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MinScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_move_sd (__m128d a, __m128d b)
+ /// MOVSD xmm, xmm
+ /// </summary>
+ public static Vector128<double> MoveScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_movemask_pd (__m128d a)
+ /// MOVMSKPD reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<long> MoveScalar(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<ulong> MoveScalar(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mul_epu32 (__m128i a, __m128i b)
+ /// PMULUDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Multiply(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_mul_pd (__m128d a, __m128d b)
+ /// MULPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_mul_sd (__m128d a, __m128d b)
+ /// MULSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mulhi_epi16 (__m128i a, __m128i b)
+ /// PMULHW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHigh(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mulhi_epu16 (__m128i a, __m128i b)
+ /// PMULHUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MultiplyHigh(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_madd_epi16 (__m128i a, __m128i b)
+ /// PMADDWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyAddAdjacent(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi16 (__m128i a, __m128i b)
+ /// PMULLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyLow(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Or(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Or(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Or(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Or(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Or(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Or(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Or(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Or(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_or_pd (__m128d a, __m128d b)
+ /// ORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Or(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_packs_epi16 (__m128i a, __m128i b)
+ /// PACKSSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> PackSignedSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_packs_epi32 (__m128i a, __m128i b)
+ /// PACKSSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> PackSignedSaturate(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_packus_epi16 (__m128i a, __m128i b)
+ /// PACKUSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> PackUnsignedSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<sbyte> SetVector128(sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<byte> SetVector128(byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<short> SetVector128(short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ushort> SetVector128(ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<int> SetVector128(int e3, int e2, int e1, int e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<uint> SetVector128(uint e3, uint e2, uint e1, uint e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<long> SetVector128(long e1, long e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ulong> SetVector128(ulong e1, ulong e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_set_pd (double e1, double e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetVector128(double e1, double e0) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_set_sd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetScalarVector128(double value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<byte> SetAllVector128(byte value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<sbyte> SetAllVector128(sbyte value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<short> SetAllVector128(short value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ushort> SetAllVector128(ushort value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<int> SetAllVector128(int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<uint> SetAllVector128(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<long> SetAllVector128(long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ulong> SetAllVector128(ulong value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetAllVector128(double value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_setzero_si128 ()
+ /// HELPER: PXOR
+ /// __m128d _mm_setzero_pd (void)
+ /// HELPER: XORPD
+ /// </summary>
+ public static Vector128<T> SetZeroVector128<T>() where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sad_epu8 (__m128i a, __m128i b)
+ /// PSADBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Shuffle(Vector128<int> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Shuffle(Vector128<uint> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_shuffle_pd (__m128d a, __m128d b, int immediate)
+ /// SHUFPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Shuffle(Vector128<double> left, Vector128<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int immediate)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleHigh(Vector128<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int control)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleHigh(Vector128<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleLow(Vector128<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleLow(Vector128<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftLeftLogical128BitLane(Vector128<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftLeftLogical128BitLane(Vector128<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical128BitLane(Vector128<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical128BitLane(Vector128<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical128BitLane(Vector128<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical128BitLane(Vector128<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical128BitLane(Vector128<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical128BitLane(Vector128<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sra_epi16 (__m128i a, __m128i count)
+ /// PSRAW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sra_epi32 (__m128i a, __m128i count)
+ /// PSRAD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srai_epi16 (__m128i a, int immediate)
+ /// PSRAW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srai_epi32 (__m128i a, int immediate)
+ /// PSRAD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftRightLogical128BitLane(Vector128<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftRightLogical128BitLane(Vector128<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical128BitLane(Vector128<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical128BitLane(Vector128<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical128BitLane(Vector128<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical128BitLane(Vector128<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical128BitLane(Vector128<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical128BitLane(Vector128<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sqrt_pd (__m128d a)
+ /// SQRTPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Sqrt(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a)
+ /// SQRTSD xmm, xmm/64
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a, __m128d b)
+ /// SQRTSD xmm, xmm/64
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_sd (double* mem_addr, __m128d a)
+ /// MOVSD m64, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_pd (double* mem_addr, __m128d a)
+ /// MOVAPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_pd (double* mem_addr, __m128d a)
+ /// MOVNTPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_pd (double* mem_addr, __m128d a)
+ /// MOVUPD m128, xmm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeh_pd (double* mem_addr, __m128d a)
+ /// MOVHPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storel_pd (double* mem_addr, __m128d a)
+ /// MOVLPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(int* address, int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(uint* address, uint value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(long* address, long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(ulong* address, ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Subtract(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Subtract(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Subtract(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Subtract(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Subtract(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Subtract(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Subtract(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Subtract(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_sub_pd (__m128d a, __m128d b)
+ /// SUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Subtract(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sub_sd (__m128d a, __m128d b)
+ /// SUBSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> SubtractScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_subs_epi8 (__m128i a, __m128i b)
+ /// PSUBSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_subs_epi16 (__m128i a, __m128i b)
+ /// PSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_subs_epu8 (__m128i a, __m128i b)
+ /// PSUBUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_subs_epu16 (__m128i a, __m128i b)
+ /// PSUBUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackHigh(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackHigh(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackHigh(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary
+ public static Vector128<ushort> UnpackHigh(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackHigh(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackHigh(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackHigh(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackHigh(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_unpackhi_pd (__m128d a, __m128d b)
+ /// UNPCKHPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackHigh(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackLow(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackLow(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackLow(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> UnpackLow(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackLow(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackLow(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackLow(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackLow(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_unpacklo_pd (__m128d a, __m128d b)
+ /// UNPCKLPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackLow(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Xor(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Xor(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Xor(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Xor(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Xor(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Xor(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Xor(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Xor(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_xor_pd (__m128d a, __m128d b)
+ /// XORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Xor(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs
new file mode 100644
index 000000000..0f8b9a8f5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs
@@ -0,0 +1,2002 @@
+// 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.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse2 : Sse
+ {
+ internal Sse2() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Add(Vector128<byte> left, Vector128<byte> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Add(Vector128<sbyte> left, Vector128<sbyte> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Add(Vector128<short> left, Vector128<short> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Add(Vector128<ushort> left, Vector128<ushort> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Add(Vector128<int> left, Vector128<int> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Add(Vector128<uint> left, Vector128<uint> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Add(Vector128<long> left, Vector128<long> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Add(Vector128<ulong> left, Vector128<ulong> right) => Add(left, right);
+ /// <summary>
+ /// __m128d _mm_add_pd (__m128d a, __m128d b)
+ /// ADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Add(Vector128<double> left, Vector128<double> right) => Add(left, right);
+
+ /// <summary>
+ /// __m128d _mm_add_sd (__m128d a, __m128d b)
+ /// ADDSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> AddScalar(Vector128<double> left, Vector128<double> right) => AddScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_adds_epi8 (__m128i a, __m128i b)
+ /// PADDSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_adds_epu8 (__m128i a, __m128i b)
+ /// PADDUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_adds_epi16 (__m128i a, __m128i b)
+ /// PADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_adds_epu16 (__m128i a, __m128i b)
+ /// PADDUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) => AddSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> And(Vector128<byte> left, Vector128<byte> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> And(Vector128<sbyte> left, Vector128<sbyte> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> And(Vector128<short> left, Vector128<short> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> And(Vector128<ushort> left, Vector128<ushort> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> And(Vector128<int> left, Vector128<int> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> And(Vector128<uint> left, Vector128<uint> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> And(Vector128<long> left, Vector128<long> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> And(Vector128<ulong> left, Vector128<ulong> right) => And(left, right);
+ /// <summary>
+ /// __m128d _mm_and_pd (__m128d a, __m128d b)
+ /// ANDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> And(Vector128<double> left, Vector128<double> right) => And(left, right);
+
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AndNot(Vector128<byte> left, Vector128<byte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AndNot(Vector128<sbyte> left, Vector128<sbyte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AndNot(Vector128<short> left, Vector128<short> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AndNot(Vector128<ushort> left, Vector128<ushort> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> AndNot(Vector128<int> left, Vector128<int> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> AndNot(Vector128<uint> left, Vector128<uint> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> AndNot(Vector128<long> left, Vector128<long> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> AndNot(Vector128<ulong> left, Vector128<ulong> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128d _mm_andnot_pd (__m128d a, __m128d b)
+ /// ADDNPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AndNot(Vector128<double> left, Vector128<double> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m128i _mm_avg_epu8 (__m128i a, __m128i b)
+ /// PAVGB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Average(Vector128<byte> left, Vector128<byte> right) => Average(left, right);
+ /// <summary>
+ /// __m128i _mm_avg_epu16 (__m128i a, __m128i b)
+ /// PAVGW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Average(Vector128<ushort> left, Vector128<ushort> right) => Average(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareEqual(Vector128<sbyte> left, Vector128<sbyte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> CompareEqual(Vector128<byte> left, Vector128<byte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareEqual(Vector128<short> left, Vector128<short> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> CompareEqual(Vector128<ushort> left, Vector128<ushort> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareEqual(Vector128<int> left, Vector128<int> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> CompareEqual(Vector128<uint> left, Vector128<uint> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128d _mm_cmpeq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqual(Vector128<double> left, Vector128<double> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comieq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomieq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqualScalar(Vector128<double> left, Vector128<double> right) => CompareEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareGreaterThan(Vector128<sbyte> left, Vector128<sbyte> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareGreaterThan(Vector128<short> left, Vector128<short> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareGreaterThan(Vector128<int> left, Vector128<int> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m128d _mm_cmpgt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThan(Vector128<double> left, Vector128<double> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// int _mm_comigt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomigt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comige_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomige_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareLessThan(Vector128<sbyte> left, Vector128<sbyte> right) => CompareLessThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmplt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareLessThan(Vector128<short> left, Vector128<short> right) => CompareLessThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmplt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareLessThan(Vector128<int> left, Vector128<int> right) => CompareLessThan(left, right);
+ /// <summary>
+ /// __m128d _mm_cmplt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThan(Vector128<double> left, Vector128<double> right) => CompareLessThan(left, right);
+
+ /// <summary>
+ /// int _mm_comilt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomilt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmplt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThanScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmple_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comile_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomile_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmple_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqual(Vector128<double> left, Vector128<double> right) => CompareNotEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comineq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomineq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThan(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThan(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanScalar(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThan(Vector128<double> left, Vector128<double> right) => CompareNotLessThan(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanScalar(Vector128<double> left, Vector128<double> right) => CompareNotLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareNotLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrdered(Vector128<double> left, Vector128<double> right) => CompareOrdered(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareOrderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnordered(Vector128<double> left, Vector128<double> right) => CompareUnordered(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cvtps_epi32 (__m128 a)
+ /// CVTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<float> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtpd_epi32 (__m128d a)
+ /// CVTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<double> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128 _mm_cvtepi32_ps (__m128i a)
+ /// CVTDQ2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<int> value) => ConvertToVector128Single(value);
+ /// <summary>
+ /// __m128 _mm_cvtpd_ps (__m128d a)
+ /// CVTPD2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<double> value) => ConvertToVector128Single(value);
+ /// <summary>
+ /// __m128d _mm_cvtepi32_pd (__m128i a)
+ /// CVTDQ2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<int> value) => ConvertToVector128Double(value);
+ /// <summary>
+ /// __m128d _mm_cvtps_pd (__m128 a)
+ /// CVTPS2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<float> value) => ConvertToVector128Double(value);
+
+ /// <summary>
+ /// double _mm_cvtsd_f64(__m128d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector128<double> value) => ConvertToDouble(value);
+ /// <summary>
+ /// int _mm_cvtsd_si32 (__m128d a)
+ /// CVTSD2SI r32, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32(Vector128<double> value) => ConvertToInt32(value);
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector128<int> value) => ConvertToInt32(value);
+ /// <summary>
+ /// __int64 _mm_cvtsd_si64 (__m128d a)
+ /// CVTSD2SI r64, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64(Vector128<double> value) => ConvertToInt64(value);
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static long ConvertToInt64(Vector128<long> value) => ConvertToInt64(value);
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector128<uint> value) => ConvertToUInt32(value);
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static ulong ConvertToUInt64(Vector128<ulong> value) => ConvertToUInt64(value);
+
+ /// <summary>
+ /// __m128d _mm_cvtsi32_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, int value) => ConvertScalarToVector128Double(upper, value);
+ /// <summary>
+ /// __m128d _mm_cvtsi64_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, long value) => ConvertScalarToVector128Double(upper, value);
+ /// <summary>
+ /// __m128d _mm_cvtss_sd (__m128d a, __m128 b)
+ /// CVTSS2SD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, Vector128<float> value) => ConvertScalarToVector128Double(upper, value);
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<int> ConvertScalarToVector128Int32(int value) => ConvertScalarToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<long> ConvertScalarToVector128Int64(long value) => ConvertScalarToVector128Int64(value);
+ /// <summary>
+ /// __m128 _mm_cvtsd_ss (__m128 a, __m128d b)
+ /// CVTSD2SS xmm, xmm/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, Vector128<double> value) => ConvertScalarToVector128Single(upper, value);
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<uint> ConvertScalarToVector128UInt32(uint value) => ConvertScalarToVector128UInt32(value);
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<ulong> ConvertScalarToVector128UInt64(ulong value) => ConvertScalarToVector128UInt64(value);
+
+ /// <summary>
+ /// __m128i _mm_cvttps_epi32 (__m128 a)
+ /// CVTTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<float> value) => ConvertToVector128Int32WithTruncation(value);
+ /// <summary>
+ /// __m128i _mm_cvttpd_epi32 (__m128d a)
+ /// CVTTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<double> value) => ConvertToVector128Int32WithTruncation(value);
+
+ /// <summary>
+ /// int _mm_cvttsd_si32 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<double> value) => ConvertToInt32WithTruncation(value);
+ /// <summary>
+ /// __int64 _mm_cvttsd_si64 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<double> value) => ConvertToInt64WithTruncation(value);
+
+ /// <summary>
+ /// __m128d _mm_div_pd (__m128d a, __m128d b)
+ /// DIVPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// __m128d _mm_div_sd (__m128d a, __m128d b)
+ /// DIVSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> DivideScalar(Vector128<double> left, Vector128<double> right) => DivideScalar(left, right);
+
+ /// <summary>
+ /// int _mm_extract_epi16 (__m128i a, int immediate)
+ /// PEXTRW reg, xmm, imm8
+ /// </summary>
+ public static ushort Extract(Vector128<ushort> value, byte index) => Extract(value, index);
+
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<short> Insert(Vector128<short> value, short data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<ushort> Insert(Vector128<ushort> value, ushort data, byte index) => Insert(value, data, index);
+
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadVector128(sbyte* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadVector128(byte* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadVector128(short* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadVector128(ushort* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadVector128(int* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadVector128(uint* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadVector128(long* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadVector128(ulong* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128d _mm_loadu_pd (double const* mem_address)
+ /// MOVUPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadVector128(double* address) => LoadVector128(address);
+
+ /// <summary>
+ /// __m128d _mm_load_sd (double const* mem_address)
+ /// MOVSD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadScalarVector128(double* address) => LoadScalarVector128(address);
+
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128(sbyte* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128(byte* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128(short* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128(ushort* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128(int* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128(uint* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128(long* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128(ulong* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128d _mm_load_pd (double const* mem_address)
+ /// MOVAPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadAlignedVector128(double* address) => LoadAlignedVector128(address);
+
+ /// <summary>
+ /// void _mm_lfence(void)
+ /// LFENCE
+ /// </summary>
+ public static void LoadFence() => LoadFence();
+
+ /// <summary>
+ /// __m128d _mm_loadh_pd (__m128d a, double const* mem_addr)
+ /// MOVHPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadHigh(Vector128<double> lower, double* address) => LoadHigh(lower, address);
+
+ /// <summary>
+ /// __m128d _mm_loadl_pd (__m128d a, double const* mem_addr)
+ /// MOVLPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadLow(Vector128<double> upper, double* address) => LoadLow(upper, address);
+
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m32
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<int> LoadScalarVector128(int* address) => LoadScalarVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m32
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<uint> LoadScalarVector128(uint* address) => LoadScalarVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<long> LoadScalarVector128(long* address) => LoadScalarVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadScalarVector128(ulong* address) => LoadScalarVector128(address);
+
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<sbyte> source, Vector128<sbyte> mask, sbyte* address) => MaskMove(source, mask, address);
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<byte> source, Vector128<byte> mask, byte* address) => MaskMove(source, mask, address);
+
+ /// <summary>
+ /// __m128i _mm_max_epu8 (__m128i a, __m128i b)
+ /// PMAXUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epi16 (__m128i a, __m128i b)
+ /// PMAXSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) => Max(left, right);
+ /// <summary>
+ /// __m128d _mm_max_pd (__m128d a, __m128d b)
+ /// MAXPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) => Max(left, right);
+
+ /// <summary>
+ /// __m128d _mm_max_sd (__m128d a, __m128d b)
+ /// MAXSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MaxScalar(Vector128<double> left, Vector128<double> right) => MaxScalar(left, right);
+
+ /// <summary>
+ /// void _mm_mfence(void)
+ /// MFENCE
+ /// </summary>
+ public static void MemoryFence() => MemoryFence();
+
+ /// <summary>
+ /// __m128i _mm_min_epu8 (__m128i a, __m128i b)
+ /// PMINUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epi16 (__m128i a, __m128i b)
+ /// PMINSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) => Min(left, right);
+ /// <summary>
+ /// __m128d _mm_min_pd (__m128d a, __m128d b)
+ /// MINPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) => Min(left, right);
+
+ /// <summary>
+ /// __m128d _mm_min_sd (__m128d a, __m128d b)
+ /// MINSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MinScalar(Vector128<double> left, Vector128<double> right) => MinScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_move_sd (__m128d a, __m128d b)
+ /// MOVSD xmm, xmm
+ /// </summary>
+ public static Vector128<double> MoveScalar(Vector128<double> upper, Vector128<double> value) => MoveScalar(upper, value);
+
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<sbyte> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<byte> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm_movemask_pd (__m128d a)
+ /// MOVMSKPD reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<double> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<long> MoveScalar(Vector128<long> value) => MoveScalar(value);
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<ulong> MoveScalar(Vector128<ulong> value) => MoveScalar(value);
+
+ /// <summary>
+ /// __m128i _mm_mul_epu32 (__m128i a, __m128i b)
+ /// PMULUDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Multiply(Vector128<uint> left, Vector128<uint> right) => Multiply(left, right);
+ /// <summary>
+ /// __m128d _mm_mul_pd (__m128d a, __m128d b)
+ /// MULPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m128d _mm_mul_sd (__m128d a, __m128d b)
+ /// MULSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyScalar(Vector128<double> left, Vector128<double> right) => MultiplyScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mulhi_epi16 (__m128i a, __m128i b)
+ /// PMULHW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHigh(Vector128<short> left, Vector128<short> right) => MultiplyHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_mulhi_epu16 (__m128i a, __m128i b)
+ /// PMULHUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MultiplyHigh(Vector128<ushort> left, Vector128<ushort> right) => MultiplyHigh(left, right);
+
+ /// <summary>
+ /// __m128i _mm_madd_epi16 (__m128i a, __m128i b)
+ /// PMADDWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyAddAdjacent(Vector128<short> left, Vector128<short> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi16 (__m128i a, __m128i b)
+ /// PMULLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyLow(Vector128<short> left, Vector128<short> right) => MultiplyLow(left, right);
+
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Or(Vector128<byte> left, Vector128<byte> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Or(Vector128<sbyte> left, Vector128<sbyte> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Or(Vector128<short> left, Vector128<short> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Or(Vector128<ushort> left, Vector128<ushort> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Or(Vector128<int> left, Vector128<int> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Or(Vector128<uint> left, Vector128<uint> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Or(Vector128<long> left, Vector128<long> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Or(Vector128<ulong> left, Vector128<ulong> right) => Or(left, right);
+ /// <summary>
+ /// __m128d _mm_or_pd (__m128d a, __m128d b)
+ /// ORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Or(Vector128<double> left, Vector128<double> right) => Or(left, right);
+
+ /// <summary>
+ /// __m128i _mm_packs_epi16 (__m128i a, __m128i b)
+ /// PACKSSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> PackSignedSaturate(Vector128<short> left, Vector128<short> right) => PackSignedSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_packs_epi32 (__m128i a, __m128i b)
+ /// PACKSSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> PackSignedSaturate(Vector128<int> left, Vector128<int> right) => PackSignedSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_packus_epi16 (__m128i a, __m128i b)
+ /// PACKUSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> PackUnsignedSaturate(Vector128<short> left, Vector128<short> right) => PackUnsignedSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<byte> SetAllVector128(byte value)
+ {
+ // Zero vector and load value et index 0
+ Vector128<byte> vector1 = Sse.StaticCast<uint, byte>(ConvertScalarToVector128UInt32(value));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- -- -- vl vl }
+ Vector128<ushort> tmpVector1 = Sse.StaticCast<byte, ushort>(UnpackLow(vector1, vector1));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- vl vl vl vl }
+ Vector128<uint> tmpVector2 = Sse.StaticCast<ushort, uint>(UnpackLow(tmpVector1, tmpVector1));
+ // Create { vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<uint, byte>(Shuffle(tmpVector2, 0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<sbyte> SetAllVector128(sbyte value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<sbyte> vector = Sse.StaticCast<int, sbyte>(ConvertScalarToVector128Int32(value));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- -- -- vl vl }
+ Vector128<short> tmpVector1 = Sse.StaticCast<sbyte, short>(UnpackLow(vector, vector));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- vl vl vl vl }
+ Vector128<int> tmpVector2 = Sse.StaticCast<short, int>(UnpackLow(tmpVector1, tmpVector1));
+ // Create { vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<int, sbyte>(Shuffle(tmpVector2, 0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<short> SetAllVector128(short value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<short> vector = Sse.StaticCast<int, short>(ConvertScalarToVector128Int32(value));
+ // Create { -- -- -- -- -- -- vl vl }
+ Vector128<int> tmpVector = Sse.StaticCast<short, int>(UnpackLow(vector, vector));
+ // Create { vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<int, short>(Shuffle(tmpVector, (byte)0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ushort> SetAllVector128(ushort value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<ushort> vector = Sse.StaticCast<uint, ushort>(ConvertScalarToVector128UInt32(value));
+ // Create { -- -- -- -- -- -- vl vl }
+ Vector128<uint> tmpVector = Sse.StaticCast<ushort, uint>(UnpackLow(vector, vector));
+ // Create { vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<uint, ushort>(Shuffle(tmpVector, (byte)0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<int> SetAllVector128(int value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<int> vector = ConvertScalarToVector128Int32(value);
+ // Create { vl vl vl vl } and return result
+ return Shuffle(vector, 0);
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<uint> SetAllVector128(uint value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<uint> vector = ConvertScalarToVector128UInt32(value);
+ // Create { vl vl vl vl } and return result
+ return Shuffle(vector, 0);
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<long> SetAllVector128(long value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<long> vector = ConvertScalarToVector128Int64(value);
+ // Create { vl vl } and return result
+ return UnpackLow(vector, vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ulong> SetAllVector128(ulong value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<ulong> vector = ConvertScalarToVector128UInt64(value);
+ // Create { vl vl } and return result
+ return UnpackLow(vector, vector);
+ }
+ /// <summary>
+ /// __m128d _mm_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<double> SetAllVector128(double value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<double> vector = SetScalarVector128(value);
+ // Create { vl vl } and return result
+ return UnpackLow(vector, vector);
+ }
+
+ /// <summary>
+ /// __m128d _mm_set_sd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetScalarVector128(double value) => SetScalarVector128(value);
+
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector128<sbyte> SetVector128(sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ sbyte* buffer = stackalloc sbyte[16];
+ buffer[0] = e0;
+ buffer[1] = e1;
+ buffer[2] = e2;
+ buffer[3] = e3;
+ buffer[4] = e4;
+ buffer[5] = e5;
+ buffer[6] = e6;
+ buffer[7] = e7;
+ buffer[8] = e8;
+ buffer[9] = e9;
+ buffer[10] = e10;
+ buffer[11] = e11;
+ buffer[12] = e12;
+ buffer[13] = e13;
+ buffer[14] = e14;
+ buffer[15] = e15;
+
+ // Load 16-byte buffer into Vector
+ return LoadVector128(buffer);
+ }
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector128<byte> SetVector128(byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ byte* buffer = stackalloc byte[16];
+ buffer[0] = e0;
+ buffer[1] = e1;
+ buffer[2] = e2;
+ buffer[3] = e3;
+ buffer[4] = e4;
+ buffer[5] = e5;
+ buffer[6] = e6;
+ buffer[7] = e7;
+ buffer[8] = e8;
+ buffer[9] = e9;
+ buffer[10] = e10;
+ buffer[11] = e11;
+ buffer[12] = e12;
+ buffer[13] = e13;
+ buffer[14] = e14;
+ buffer[15] = e15;
+
+ // Load 16-byte buffer into Vector
+ return LoadVector128(buffer);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<short> SetVector128(short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e0 et index 0
+ Vector128<int> e0Vector = ConvertScalarToVector128Int32(e0);
+ Vector128<short> vector = Sse.StaticCast<int, short>(e0Vector);
+ // Insert e1 ... e7 at corresponding index
+ vector = Insert(vector, e1, (byte)1);
+ vector = Insert(vector, e2, (byte)2);
+ vector = Insert(vector, e3, (byte)3);
+ vector = Insert(vector, e4, (byte)4);
+ vector = Insert(vector, e5, (byte)5);
+ vector = Insert(vector, e6, (byte)6);
+ return Insert(vector, e7, (byte)7);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ushort> SetVector128(ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e0 et index 0
+ Vector128<uint> e0vector = ConvertScalarToVector128UInt32(e0);
+ Vector128<ushort> vector = Sse.StaticCast<uint, ushort>(e0vector);
+ // Insert e1 ... e7 at corresponding index
+ vector = Insert(vector, e1, (byte)1);
+ vector = Insert(vector, e2, (byte)2);
+ vector = Insert(vector, e3, (byte)3);
+ vector = Insert(vector, e4, (byte)4);
+ vector = Insert(vector, e5, (byte)5);
+ vector = Insert(vector, e6, (byte)6);
+ return Insert(vector, e7, (byte)7);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<int> SetVector128(int e3, int e2, int e1, int e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e2 et index 0
+ Vector128<int> e2Vector = ConvertScalarToVector128Int32(e2);
+ Vector128<int> e1Vector = ConvertScalarToVector128Int32(e1);
+ Vector128<int> e0Vector = ConvertScalarToVector128Int32(e0);
+ // Create { -- -- e2 e0 }
+ e0Vector = UnpackLow(e0Vector, e2Vector);
+ e2Vector = ConvertScalarToVector128Int32(e3);
+ // Create { -- -- e3 e1 }
+ e1Vector = UnpackLow(e1Vector, e2Vector);
+ // Create { e3 e2 e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<uint> SetVector128(uint e3, uint e2, uint e1, uint e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e2 et index 0
+ Vector128<uint> e2Vector = ConvertScalarToVector128UInt32(e2);
+ Vector128<uint> e1Vector = ConvertScalarToVector128UInt32(e1);
+ Vector128<uint> e0Vector = ConvertScalarToVector128UInt32(e0);
+ // Create { -- -- e2 e0 }
+ e0Vector = UnpackLow(e0Vector, e2Vector);
+ e2Vector = ConvertScalarToVector128UInt32(e3);
+ // Create { -- -- e3 e1 }
+ e1Vector = UnpackLow(e1Vector, e2Vector);
+ // Create { e3 e2 e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<long> SetVector128(long e1, long e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e1 et index 0
+ Vector128<long> e1Vector = ConvertScalarToVector128Int64(e1);
+ Vector128<long> e0vector = ConvertScalarToVector128Int64(e0);
+ // Create { e1 e0 } and return result
+ return UnpackLow(e0vector, e1Vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ulong> SetVector128(ulong e1, ulong e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e1 et index 0
+ Vector128<ulong> e1vector = ConvertScalarToVector128UInt64(e1);
+ Vector128<ulong> e0Vector = ConvertScalarToVector128UInt64(e0);
+ // Create { e1 e0 } and return result
+ return UnpackLow(e0Vector, e1vector);
+ }
+ /// <summary>
+ /// __m128d _mm_set_pd (double e1, double e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector128<double> SetVector128(double e1, double e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e1 et index 0
+ Vector128<double> e1Vector = SetScalarVector128(e1);
+ Vector128<double> e0Vector = SetScalarVector128(e0);
+ // Create { e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+
+ /// <summary>
+ /// __m128i _mm_setzero_si128 ()
+ /// HELPER: PXOR
+ /// __m128d _mm_setzero_pd (void)
+ /// HELPER: XORPD
+ /// </summary>
+ public static Vector128<T> SetZeroVector128<T>() where T : struct
+ {
+ return SetZeroVector128<T>();
+ }
+
+ /// <summary>
+ /// __m128i _mm_sad_epu8 (__m128i a, __m128i b)
+ /// PSADBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right) => SumAbsoluteDifferences(left, right);
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Shuffle(Vector128<int> value, byte control) => Shuffle(value, control);
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Shuffle(Vector128<uint> value, byte control) => Shuffle(value, control);
+ /// <summary>
+ /// __m128d _mm_shuffle_pd (__m128d a, __m128d b, int immediate)
+ /// SHUFPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Shuffle(Vector128<double> left, Vector128<double> right, byte control) => Shuffle(left, right, control);
+
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int immediate)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleHigh(Vector128<short> value, byte control) => ShuffleHigh(value, control);
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int control)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleHigh(Vector128<ushort> value, byte control) => ShuffleHigh(value, control);
+
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleLow(Vector128<short> value, byte control) => ShuffleLow(value, control);
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleLow(Vector128<ushort> value, byte control) => ShuffleLow(value, control);
+
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, Vector128<short> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, Vector128<ushort> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, Vector128<int> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, Vector128<uint> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, Vector128<long> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, Vector128<ulong> count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, byte count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftLeftLogical128BitLane(Vector128<sbyte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftLeftLogical128BitLane(Vector128<byte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical128BitLane(Vector128<short> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical128BitLane(Vector128<ushort> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical128BitLane(Vector128<int> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical128BitLane(Vector128<uint> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical128BitLane(Vector128<long> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical128BitLane(Vector128<ulong> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m128i _mm_sra_epi16 (__m128i a, __m128i count)
+ /// PSRAW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, Vector128<short> count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// __m128i _mm_sra_epi32 (__m128i a, __m128i count)
+ /// PSRAD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, Vector128<int> count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srai_epi16 (__m128i a, int immediate)
+ /// PSRAW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, byte count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// __m128i _mm_srai_epi32 (__m128i a, int immediate)
+ /// PSRAD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, byte count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, Vector128<short> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, Vector128<ushort> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, Vector128<int> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, Vector128<uint> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, Vector128<long> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, Vector128<ulong> count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, byte count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftRightLogical128BitLane(Vector128<sbyte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftRightLogical128BitLane(Vector128<byte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical128BitLane(Vector128<short> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical128BitLane(Vector128<ushort> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical128BitLane(Vector128<int> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical128BitLane(Vector128<uint> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical128BitLane(Vector128<long> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical128BitLane(Vector128<ulong> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m128d _mm_sqrt_pd (__m128d a)
+ /// SQRTPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Sqrt(Vector128<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a)
+ /// SQRTSD xmm, xmm/64
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> value) => SqrtScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a, __m128d b)
+ /// SQRTSD xmm, xmm/64
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> upper, Vector128<double> value) => SqrtScalar(upper, value);
+
+ /// <summary>
+ /// void _mm_store_sd (double* mem_addr, __m128d a)
+ /// MOVSD m64, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(double* address, Vector128<double> source) => StoreScalar(address, source);
+
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector128<sbyte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector128<byte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector128<short> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector128<ushort> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector128<int> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector128<uint> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector128<long> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector128<ulong> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_pd (double* mem_addr, __m128d a)
+ /// MOVAPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector128<double> source) => StoreAligned(address, source);
+
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector128<sbyte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector128<byte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector128<short> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector128<ushort> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector128<int> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector128<uint> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector128<long> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector128<ulong> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_pd (double* mem_addr, __m128d a)
+ /// MOVNTPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector128<double> source) => StoreAlignedNonTemporal(address, source);
+
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector128<sbyte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector128<byte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector128<short> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector128<ushort> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector128<int> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector128<uint> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector128<long> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector128<ulong> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_pd (double* mem_addr, __m128d a)
+ /// MOVUPD m128, xmm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector128<double> source) => Store(address, source);
+
+ /// <summary>
+ /// void _mm_storeh_pd (double* mem_addr, __m128d a)
+ /// MOVHPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(double* address, Vector128<double> source) => StoreHigh(address, source);
+
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(long* address, Vector128<long> source) => StoreLow(address, source);
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(ulong* address, Vector128<ulong> source) => StoreLow(address, source);
+ /// <summary>
+ /// void _mm_storel_pd (double* mem_addr, __m128d a)
+ /// MOVLPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(double* address, Vector128<double> source) => StoreLow(address, source);
+
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(int* address, int value) => StoreNonTemporal(address, value);
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(uint* address, uint value) => StoreNonTemporal(address, value);
+
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(long* address, long value) => StoreNonTemporal(address, value);
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(ulong* address, ulong value) => StoreNonTemporal(address, value);
+
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Subtract(Vector128<byte> left, Vector128<byte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Subtract(Vector128<sbyte> left, Vector128<sbyte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Subtract(Vector128<short> left, Vector128<short> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Subtract(Vector128<ushort> left, Vector128<ushort> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Subtract(Vector128<int> left, Vector128<int> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Subtract(Vector128<uint> left, Vector128<uint> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Subtract(Vector128<long> left, Vector128<long> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Subtract(Vector128<ulong> left, Vector128<ulong> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128d _mm_sub_pd (__m128d a, __m128d b)
+ /// SUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Subtract(Vector128<double> left, Vector128<double> right) => Subtract(left, right);
+
+ /// <summary>
+ /// __m128d _mm_sub_sd (__m128d a, __m128d b)
+ /// SUBSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> SubtractScalar(Vector128<double> left, Vector128<double> right) => SubtractScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_subs_epi8 (__m128i a, __m128i b)
+ /// PSUBSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_subs_epi16 (__m128i a, __m128i b)
+ /// PSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_subs_epu8 (__m128i a, __m128i b)
+ /// PSUBUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_subs_epu16 (__m128i a, __m128i b)
+ /// PSUBUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) => SubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackHigh(Vector128<byte> left, Vector128<byte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackHigh(Vector128<sbyte> left, Vector128<sbyte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackHigh(Vector128<short> left, Vector128<short> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary
+ public static Vector128<ushort> UnpackHigh(Vector128<ushort> left, Vector128<ushort> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackHigh(Vector128<int> left, Vector128<int> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackHigh(Vector128<uint> left, Vector128<uint> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackHigh(Vector128<long> left, Vector128<long> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackHigh(Vector128<ulong> left, Vector128<ulong> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128d _mm_unpackhi_pd (__m128d a, __m128d b)
+ /// UNPCKHPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackHigh(Vector128<double> left, Vector128<double> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackLow(Vector128<byte> left, Vector128<byte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackLow(Vector128<sbyte> left, Vector128<sbyte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackLow(Vector128<short> left, Vector128<short> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> UnpackLow(Vector128<ushort> left, Vector128<ushort> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackLow(Vector128<int> left, Vector128<int> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackLow(Vector128<uint> left, Vector128<uint> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackLow(Vector128<long> left, Vector128<long> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackLow(Vector128<ulong> left, Vector128<ulong> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128d _mm_unpacklo_pd (__m128d a, __m128d b)
+ /// UNPCKLPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackLow(Vector128<double> left, Vector128<double> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Xor(Vector128<byte> left, Vector128<byte> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Xor(Vector128<sbyte> left, Vector128<sbyte> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Xor(Vector128<short> left, Vector128<short> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Xor(Vector128<ushort> left, Vector128<ushort> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Xor(Vector128<int> left, Vector128<int> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Xor(Vector128<uint> left, Vector128<uint> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Xor(Vector128<long> left, Vector128<long> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Xor(Vector128<ulong> left, Vector128<ulong> right) => Xor(left, right);
+ /// <summary>
+ /// __m128d _mm_xor_pd (__m128d a, __m128d b)
+ /// XORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Xor(Vector128<double> left, Vector128<double> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs
new file mode 100644
index 000000000..f00426644
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs
@@ -0,0 +1,91 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse3 : Sse2
+ {
+ internal Sse3() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128 _mm_addsub_ps (__m128 a, __m128 b)
+ /// ADDSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AddSubtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_addsub_pd (__m128d a, __m128d b)
+ /// ADDSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AddSubtract(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_hadd_ps (__m128 a, __m128 b)
+ /// HADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalAdd(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_hadd_pd (__m128d a, __m128d b)
+ /// HADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalAdd(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_hsub_ps (__m128 a, __m128 b)
+ /// HSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalSubtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_hsub_pd (__m128d a, __m128d b)
+ /// HSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalSubtract(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_loaddup_pd (double const* mem_addr)
+ /// MOVDDUP xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadAndDuplicateToVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_lddqu_si128 (__m128i const* mem_addr)
+ /// LDDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadDquVector128(sbyte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<byte> LoadDquVector128(byte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<short> LoadDquVector128(short* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<ushort> LoadDquVector128(ushort* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<int> LoadDquVector128(int* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<uint> LoadDquVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<long> LoadDquVector128(long* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<ulong> LoadDquVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_movedup_pd (__m128d a)
+ /// MOVDDUP xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MoveAndDuplicate(Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_movehdup_ps (__m128 a)
+ /// MOVSHDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveHighAndDuplicate(Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_moveldup_ps (__m128 a)
+ /// MOVSLDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveLowAndDuplicate(Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs
new file mode 100644
index 000000000..7c0eaad05
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs
@@ -0,0 +1,90 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse3 : Sse2
+ {
+ internal Sse3() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128 _mm_addsub_ps (__m128 a, __m128 b)
+ /// ADDSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AddSubtract(Vector128<float> left, Vector128<float> right) => AddSubtract(left, right);
+ /// <summary>
+ /// __m128d _mm_addsub_pd (__m128d a, __m128d b)
+ /// ADDSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AddSubtract(Vector128<double> left, Vector128<double> right) => AddSubtract(left, right);
+
+ /// <summary>
+ /// __m128 _mm_hadd_ps (__m128 a, __m128 b)
+ /// HADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalAdd(Vector128<float> left, Vector128<float> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m128d _mm_hadd_pd (__m128d a, __m128d b)
+ /// HADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalAdd(Vector128<double> left, Vector128<double> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m128 _mm_hsub_ps (__m128 a, __m128 b)
+ /// HSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalSubtract(Vector128<float> left, Vector128<float> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m128d _mm_hsub_pd (__m128d a, __m128d b)
+ /// HSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalSubtract(Vector128<double> left, Vector128<double> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m128d _mm_loaddup_pd (double const* mem_addr)
+ /// MOVDDUP xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadAndDuplicateToVector128(double* address) => LoadAndDuplicateToVector128(address);
+
+ /// <summary>
+ /// __m128i _mm_lddqu_si128 (__m128i const* mem_addr)
+ /// LDDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadDquVector128(sbyte* address) => LoadDquVector128(address);
+ public static unsafe Vector128<byte> LoadDquVector128(byte* address) => LoadDquVector128(address);
+ public static unsafe Vector128<short> LoadDquVector128(short* address) => LoadDquVector128(address);
+ public static unsafe Vector128<ushort> LoadDquVector128(ushort* address) => LoadDquVector128(address);
+ public static unsafe Vector128<int> LoadDquVector128(int* address) => LoadDquVector128(address);
+ public static unsafe Vector128<uint> LoadDquVector128(uint* address) => LoadDquVector128(address);
+ public static unsafe Vector128<long> LoadDquVector128(long* address) => LoadDquVector128(address);
+ public static unsafe Vector128<ulong> LoadDquVector128(ulong* address) => LoadDquVector128(address);
+
+ /// <summary>
+ /// __m128d _mm_movedup_pd (__m128d a)
+ /// MOVDDUP xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MoveAndDuplicate(Vector128<double> source) => MoveAndDuplicate(source);
+
+ /// <summary>
+ /// __m128 _mm_movehdup_ps (__m128 a)
+ /// MOVSHDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveHighAndDuplicate(Vector128<float> source) => MoveHighAndDuplicate(source);
+
+ /// <summary>
+ /// __m128 _mm_moveldup_ps (__m128 a)
+ /// MOVSLDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveLowAndDuplicate(Vector128<float> source) => MoveLowAndDuplicate(source);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs
new file mode 100644
index 000000000..58d06fa14
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs
@@ -0,0 +1,636 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse41 : Ssse3
+ {
+ internal Sse41() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<short> Blend(Vector128<short> left, Vector128<short> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<ushort> Blend(Vector128<ushort> left, Vector128<ushort> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_blend_ps (__m128 a, __m128 b, const int imm8)
+ /// BLENDPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Blend(Vector128<float> left, Vector128<float> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_blend_pd (__m128d a, __m128d b, const int imm8)
+ /// BLENDPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Blend(Vector128<double> left, Vector128<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<sbyte> BlendVariable(Vector128<sbyte> left, Vector128<sbyte> right, Vector128<sbyte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<byte> BlendVariable(Vector128<byte> left, Vector128<byte> right, Vector128<byte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_blendv_ps (__m128 a, __m128 b, __m128 mask)
+ /// BLENDVPS xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<float> BlendVariable(Vector128<float> left, Vector128<float> right, Vector128<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_blendv_pd (__m128d a, __m128d b, __m128d mask)
+ /// BLENDVPD xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<double> BlendVariable(Vector128<double> left, Vector128<double> right, Vector128<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_ceil_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> Ceiling(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_ceil_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> Ceiling(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareEqual(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> CompareEqual(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi16 (__m128i a)
+ /// PMOVSXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi16 (__m128i a)
+ /// PMOVZXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi32 (__m128i a)
+ /// PMOVSXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi32 (__m128i a)
+ /// PMOVZXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi32 (__m128i a)
+ /// PMOVSXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi32 (__m128i a)
+ /// PMOVZXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi64 (__m128i a)
+ /// PMOVSXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi64 (__m128i a)
+ /// PMOVZXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi64 (__m128i a)
+ /// PMOVSXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi64 (__m128i a)
+ /// PMOVZXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi32_epi64 (__m128i a)
+ /// PMOVSXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu32_epi64 (__m128i a)
+ /// PMOVZXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8)
+ /// DPPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> DotProduct(Vector128<float> left, Vector128<float> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_dp_pd (__m128d a, __m128d b, const int imm8)
+ /// DPPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> DotProduct(Vector128<double> left, Vector128<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_extract_epi8 (__m128i a, const int imm8)
+ /// PEXTRB reg/m8, xmm, imm8
+ /// </summary>
+ public static byte Extract(Vector128<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static int Extract(Vector128<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static uint Extract(Vector128<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static long Extract(Vector128<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static ulong Extract(Vector128<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_extract_ps (__m128 a, const int imm8)
+ /// EXTRACTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static float Extract(Vector128<float> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_floor_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> Floor(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_floor_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> Floor(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<sbyte> Insert(Vector128<sbyte> value, sbyte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<byte> Insert(Vector128<byte> value, byte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<int> Insert(Vector128<int> value, int data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<uint> Insert(Vector128<uint> value, uint data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<long> Insert(Vector128<long> value, long data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<ulong> Insert(Vector128<ulong> value, ulong data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_insert_ps (__m128 a, __m128 b, const int imm8)
+ /// INSERTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<float> Insert(Vector128<float> value, Vector128<float> data, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_max_epi8 (__m128i a, __m128i b)
+ /// PMAXSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epu16 (__m128i a, __m128i b)
+ /// PMAXUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epi32 (__m128i a, __m128i b)
+ /// PMAXSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epu32 (__m128i a, __m128i b)
+ /// PMAXUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_min_epi8 (__m128i a, __m128i b)
+ /// PMINSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epu16 (__m128i a, __m128i b)
+ /// PMINUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epi32 (__m128i a, __m128i b)
+ /// PMINSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epu32 (__m128i a, __m128i b)
+ /// PMINUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_minpos_epu16 (__m128i a)
+ /// PHMINPOSUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MinHorizontal(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mpsadbw_epu8 (__m128i a, __m128i b, const int imm8)
+ /// MPSADBW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> MultipleSumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mul_epi32 (__m128i a, __m128i b)
+ /// PMULDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Multiply(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi32 (__m128i a, __m128i b)
+ /// PMULLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyLow(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_packus_epi32 (__m128i a, __m128i b)
+ /// PACKUSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> PackUnsignedSaturate(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_round_ps (__m128 a, int rounding)
+ /// ROUNDPS xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<float> RoundToNearestInteger(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinity(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinity(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZero(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirection(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_round_pd (__m128d a, int rounding)
+ /// ROUNDPD xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<double> RoundToNearestInteger(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinity(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinity(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZero(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirection(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128NonTemporal(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128NonTemporal(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128NonTemporal(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128NonTemporal(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128NonTemporal(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128NonTemporal(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128NonTemporal(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128NonTemporal(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_test_all_ones (__m128i a)
+ /// HELPER
+ /// </summary>
+ public static bool TestAllOnes(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_test_all_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestAllZeros(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_test_mix_ones_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestMixOnesZeros(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testnzc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testz_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs
new file mode 100644
index 000000000..2547e41db
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs
@@ -0,0 +1,636 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse41 : Ssse3
+ {
+ internal Sse41() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<short> Blend(Vector128<short> left, Vector128<short> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<ushort> Blend(Vector128<ushort> left, Vector128<ushort> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128 _mm_blend_ps (__m128 a, __m128 b, const int imm8)
+ /// BLENDPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Blend(Vector128<float> left, Vector128<float> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128d _mm_blend_pd (__m128d a, __m128d b, const int imm8)
+ /// BLENDPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Blend(Vector128<double> left, Vector128<double> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<sbyte> BlendVariable(Vector128<sbyte> left, Vector128<sbyte> right, Vector128<sbyte> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<byte> BlendVariable(Vector128<byte> left, Vector128<byte> right, Vector128<byte> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m128 _mm_blendv_ps (__m128 a, __m128 b, __m128 mask)
+ /// BLENDVPS xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<float> BlendVariable(Vector128<float> left, Vector128<float> right, Vector128<float> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m128d _mm_blendv_pd (__m128d a, __m128d b, __m128d mask)
+ /// BLENDVPD xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<double> BlendVariable(Vector128<double> left, Vector128<double> right, Vector128<double> mask) => BlendVariable(left, right, mask);
+
+ /// <summary>
+ /// __m128 _mm_ceil_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> Ceiling(Vector128<float> value) => Ceiling(value);
+ /// <summary>
+ /// __m128d _mm_ceil_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> Ceiling(Vector128<double> value) => Ceiling(value);
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> value) => CeilingScalar(value);
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> value) => CeilingScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> upper, Vector128<double> value) => CeilingScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> upper, Vector128<float> value) => CeilingScalar(upper, value);
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareEqual(Vector128<long> left, Vector128<long> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> CompareEqual(Vector128<ulong> left, Vector128<ulong> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi16 (__m128i a)
+ /// PMOVSXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<sbyte> value) => ConvertToVector128Int16(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi16 (__m128i a)
+ /// PMOVZXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<byte> value) => ConvertToVector128Int16(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi32 (__m128i a)
+ /// PMOVSXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<sbyte> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi32 (__m128i a)
+ /// PMOVZXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<byte> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi32 (__m128i a)
+ /// PMOVSXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<short> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi32 (__m128i a)
+ /// PMOVZXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<ushort> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi64 (__m128i a)
+ /// PMOVSXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<sbyte> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi64 (__m128i a)
+ /// PMOVZXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<byte> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi64 (__m128i a)
+ /// PMOVSXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<short> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi64 (__m128i a)
+ /// PMOVZXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<ushort> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi32_epi64 (__m128i a)
+ /// PMOVSXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<int> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu32_epi64 (__m128i a)
+ /// PMOVZXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<uint> value) => ConvertToVector128Int64(value);
+
+ /// <summary>
+ /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8)
+ /// DPPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> DotProduct(Vector128<float> left, Vector128<float> right, byte control) => DotProduct(left, right, control);
+ /// <summary>
+ /// __m128d _mm_dp_pd (__m128d a, __m128d b, const int imm8)
+ /// DPPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> DotProduct(Vector128<double> left, Vector128<double> right, byte control) => DotProduct(left, right, control);
+
+ /// <summary>
+ /// int _mm_extract_epi8 (__m128i a, const int imm8)
+ /// PEXTRB reg/m8, xmm, imm8
+ /// </summary>
+ public static byte Extract(Vector128<byte> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static int Extract(Vector128<int> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static uint Extract(Vector128<uint> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static long Extract(Vector128<long> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static ulong Extract(Vector128<ulong> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// int _mm_extract_ps (__m128 a, const int imm8)
+ /// EXTRACTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static float Extract(Vector128<float> value, byte index) => Extract(value, index);
+
+ /// <summary>
+ /// __m128 _mm_floor_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> Floor(Vector128<float> value) => Floor(value);
+ /// <summary>
+ /// __m128d _mm_floor_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> Floor(Vector128<double> value) => Floor(value);
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> value) => FloorScalar(value);
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> value) => FloorScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> upper, Vector128<double> value) => FloorScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> upper, Vector128<float> value) => FloorScalar(upper, value);
+
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<sbyte> Insert(Vector128<sbyte> value, sbyte data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<byte> Insert(Vector128<byte> value, byte data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<int> Insert(Vector128<int> value, int data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<uint> Insert(Vector128<uint> value, uint data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<long> Insert(Vector128<long> value, long data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<ulong> Insert(Vector128<ulong> value, ulong data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128 _mm_insert_ps (__m128 a, __m128 b, const int imm8)
+ /// INSERTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<float> Insert(Vector128<float> value, Vector128<float> data, byte index) => Insert(value, data, index);
+
+ /// <summary>
+ /// __m128i _mm_max_epi8 (__m128i a, __m128i b)
+ /// PMAXSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epu16 (__m128i a, __m128i b)
+ /// PMAXUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epi32 (__m128i a, __m128i b)
+ /// PMAXSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epu32 (__m128i a, __m128i b)
+ /// PMAXUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) => Max(left, right);
+
+ /// <summary>
+ /// __m128i _mm_min_epi8 (__m128i a, __m128i b)
+ /// PMINSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epu16 (__m128i a, __m128i b)
+ /// PMINUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epi32 (__m128i a, __m128i b)
+ /// PMINSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epu32 (__m128i a, __m128i b)
+ /// PMINUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) => Min(left, right);
+
+ /// <summary>
+ /// __m128i _mm_minpos_epu16 (__m128i a)
+ /// PHMINPOSUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MinHorizontal(Vector128<ushort> value) => MinHorizontal(value);
+
+ /// <summary>
+ /// __m128i _mm_mpsadbw_epu8 (__m128i a, __m128i b, const int imm8)
+ /// MPSADBW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> MultipleSumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right, byte mask) => MultipleSumAbsoluteDifferences(left, right, mask);
+
+ /// <summary>
+ /// __m128i _mm_mul_epi32 (__m128i a, __m128i b)
+ /// PMULDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Multiply(Vector128<int> left, Vector128<int> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi32 (__m128i a, __m128i b)
+ /// PMULLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyLow(Vector128<int> left, Vector128<int> right) => MultiplyLow(left, right);
+
+ /// <summary>
+ /// __m128i _mm_packus_epi32 (__m128i a, __m128i b)
+ /// PACKUSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> PackUnsignedSaturate(Vector128<int> left, Vector128<int> right) => PackUnsignedSaturate(left, right);
+
+ /// <summary>
+ /// __m128 _mm_round_ps (__m128 a, int rounding)
+ /// ROUNDPS xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<float> RoundToNearestInteger(Vector128<float> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinity(Vector128<float> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinity(Vector128<float> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZero(Vector128<float> value) => RoundToZero(value);
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirection(Vector128<float> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m128d _mm_round_pd (__m128d a, int rounding)
+ /// ROUNDPD xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<double> RoundToNearestInteger(Vector128<double> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinity(Vector128<double> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinity(Vector128<double> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZero(Vector128<double> value) => RoundToZero(value);
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirection(Vector128<double> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> value) => RoundCurrentDirectionScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> value) => RoundToNearestIntegerScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> value) => RoundToNegativeInfinityScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> value) => RoundToPositiveInfinityScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> value) => RoundToZeroScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> upper, Vector128<double> value) => RoundCurrentDirectionScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> upper, Vector128<double> value) => RoundToNearestIntegerScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> upper, Vector128<double> value) => RoundToNegativeInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> upper, Vector128<double> value) => RoundToPositiveInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> upper, Vector128<double> value) => RoundToZeroScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> value) => RoundCurrentDirectionScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> value) => RoundToNearestIntegerScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> value) => RoundToNegativeInfinityScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> value) => RoundToPositiveInfinityScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> value) => RoundToZeroScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> upper, Vector128<float> value) => RoundCurrentDirectionScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> upper, Vector128<float> value) => RoundToNearestIntegerScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> upper, Vector128<float> value) => RoundToNegativeInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> upper, Vector128<float> value) => RoundToPositiveInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> upper, Vector128<float> value) => RoundToZeroScalar(upper, value);
+
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128NonTemporal(sbyte* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128NonTemporal(byte* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128NonTemporal(short* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128NonTemporal(ushort* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128NonTemporal(int* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128NonTemporal(uint* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128NonTemporal(long* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128NonTemporal(ulong* address) => LoadAlignedVector128NonTemporal(address);
+
+ /// <summary>
+ /// int _mm_test_all_ones (__m128i a)
+ /// HELPER
+ /// </summary>
+ public static bool TestAllOnes(Vector128<sbyte> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<byte> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<short> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<ushort> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<int> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<uint> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<long> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<ulong> value) => TestAllOnes(value);
+
+ /// <summary>
+ /// int _mm_test_all_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestAllZeros(Vector128<sbyte> left, Vector128<sbyte> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<byte> left, Vector128<byte> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<short> left, Vector128<short> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<ushort> left, Vector128<ushort> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<int> left, Vector128<int> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<uint> left, Vector128<uint> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<long> left, Vector128<long> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<ulong> left, Vector128<ulong> right) => TestAllZeros(left, right);
+
+ /// <summary>
+ /// int _mm_testc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<sbyte> left, Vector128<sbyte> right) => TestC(left, right);
+ public static bool TestC(Vector128<byte> left, Vector128<byte> right) => TestC(left, right);
+ public static bool TestC(Vector128<short> left, Vector128<short> right) => TestC(left, right);
+ public static bool TestC(Vector128<ushort> left, Vector128<ushort> right) => TestC(left, right);
+ public static bool TestC(Vector128<int> left, Vector128<int> right) => TestC(left, right);
+ public static bool TestC(Vector128<uint> left, Vector128<uint> right) => TestC(left, right);
+ public static bool TestC(Vector128<long> left, Vector128<long> right) => TestC(left, right);
+ public static bool TestC(Vector128<ulong> left, Vector128<ulong> right) => TestC(left, right);
+
+ /// <summary>
+ /// int _mm_test_mix_ones_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestMixOnesZeros(Vector128<sbyte> left, Vector128<sbyte> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<byte> left, Vector128<byte> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<short> left, Vector128<short> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<ushort> left, Vector128<ushort> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<int> left, Vector128<int> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<uint> left, Vector128<uint> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<long> left, Vector128<long> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<ulong> left, Vector128<ulong> right) => TestMixOnesZeros(left, right);
+
+ /// <summary>
+ /// int _mm_testnzc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<sbyte> left, Vector128<sbyte> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<byte> left, Vector128<byte> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<short> left, Vector128<short> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<ushort> left, Vector128<ushort> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<int> left, Vector128<int> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<uint> left, Vector128<uint> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<long> left, Vector128<long> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<ulong> left, Vector128<ulong> right) => TestNotZAndNotC(left, right);
+
+ /// <summary>
+ /// int _mm_testz_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<sbyte> left, Vector128<sbyte> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<byte> left, Vector128<byte> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<short> left, Vector128<short> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<ushort> left, Vector128<ushort> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<int> left, Vector128<int> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<uint> left, Vector128<uint> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<long> left, Vector128<long> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<ulong> left, Vector128<ulong> right) => TestZ(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs
new file mode 100644
index 000000000..8ea2d6f07
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs
@@ -0,0 +1,304 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse42 : Sse41
+ {
+ internal Sse42() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<sbyte> left, Vector128<sbyte> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<byte> left, Vector128<byte> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<short> left, Vector128<short> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<ushort> left, Vector128<ushort> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi64 (__m128i a, __m128i b)
+ /// PCMPGTQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareGreaterThan(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _mm_crc32_u8 (unsigned int crc, unsigned char v)
+ /// CRC32 reg, reg/m8
+ /// </summary>
+ public static uint Crc32(uint crc, byte data) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned int _mm_crc32_u16 (unsigned int crc, unsigned short v)
+ /// CRC32 reg, reg/m16
+ /// </summary>
+ public static uint Crc32(uint crc, ushort data) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned int _mm_crc32_u32 (unsigned int crc, unsigned int v)
+ /// CRC32 reg, reg/m32
+ /// </summary>
+ public static uint Crc32(uint crc, uint data) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _mm_crc32_u64 (unsigned __int64 crc, unsigned __int64 v)
+ /// CRC32 reg, reg/m64
+ /// </summary>
+ public static ulong Crc32(ulong crc, ulong data) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs
new file mode 100644
index 000000000..a7353382b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs
@@ -0,0 +1,304 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse42 : Sse41
+ {
+ internal Sse42() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<sbyte> left, Vector128<sbyte> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<byte> left, Vector128<byte> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<short> left, Vector128<short> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<ushort> left, Vector128<ushort> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi64 (__m128i a, __m128i b)
+ /// PCMPGTQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareGreaterThan(Vector128<long> left, Vector128<long> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// unsigned int _mm_crc32_u8 (unsigned int crc, unsigned char v)
+ /// CRC32 reg, reg/m8
+ /// </summary>
+ public static uint Crc32(uint crc, byte data) => Crc32(crc, data);
+ /// <summary>
+ /// unsigned int _mm_crc32_u16 (unsigned int crc, unsigned short v)
+ /// CRC32 reg, reg/m16
+ /// </summary>
+ public static uint Crc32(uint crc, ushort data) => Crc32(crc, data);
+ /// <summary>
+ /// unsigned int _mm_crc32_u32 (unsigned int crc, unsigned int v)
+ /// CRC32 reg, reg/m32
+ /// </summary>
+ public static uint Crc32(uint crc, uint data) => Crc32(crc, data);
+ /// <summary>
+ /// unsigned __int64 _mm_crc32_u64 (unsigned __int64 crc, unsigned __int64 v)
+ /// CRC32 reg, reg/m64
+ /// </summary>
+ public static ulong Crc32(ulong crc, ulong data) => Crc32(crc, data);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs
new file mode 100644
index 000000000..a99f7f6a6
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs
@@ -0,0 +1,116 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Ssse3 : Sse3
+ {
+ internal Ssse3() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_abs_epi8 (__m128i a)
+ /// PABSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Abs(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_abs_epi16 (__m128i a)
+ /// PABSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Abs(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_abs_epi32 (__m128i a)
+ /// PABSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Abs(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_alignr_epi8 (__m128i a, __m128i b, int count)
+ /// PALIGNR xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<sbyte> AlignRight(Vector128<sbyte> left, Vector128<sbyte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hadd_epi16 (__m128i a, __m128i b)
+ /// PHADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAdd(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_hadd_epi32 (__m128i a, __m128i b)
+ /// PHADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalAdd(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hadds_epi16 (__m128i a, __m128i b)
+ /// PHADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAddSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hsub_epi16 (__m128i a, __m128i b)
+ /// PHSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtract(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_hsub_epi32 (__m128i a, __m128i b)
+ /// PHSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalSubtract(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hsubs_epi16 (__m128i a, __m128i b)
+ /// PHSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtractSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_maddubs_epi16 (__m128i a, __m128i b)
+ /// PMADDUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyAddAdjacent(Vector128<byte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mulhrs_epi16 (__m128i a, __m128i b)
+ /// PMULHRSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHighRoundScale(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Shuffle(Vector128<sbyte> value, Vector128<sbyte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Shuffle(Vector128<byte> value, Vector128<byte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sign_epi8 (__m128i a, __m128i b)
+ /// PSIGNB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Sign(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sign_epi16 (__m128i a, __m128i b)
+ /// PSIGNW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Sign(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sign_epi32 (__m128i a, __m128i b)
+ /// PSIGND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Sign(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs
new file mode 100644
index 000000000..6fd777887
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs
@@ -0,0 +1,116 @@
+// 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.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Ssse3 : Sse3
+ {
+ internal Ssse3() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_abs_epi8 (__m128i a)
+ /// PABSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Abs(Vector128<sbyte> value) => Abs(value);
+ /// <summary>
+ /// __m128i _mm_abs_epi16 (__m128i a)
+ /// PABSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Abs(Vector128<short> value) => Abs(value);
+ /// <summary>
+ /// __m128i _mm_abs_epi32 (__m128i a)
+ /// PABSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Abs(Vector128<int> value) => Abs(value);
+
+ /// <summary>
+ /// __m128i _mm_alignr_epi8 (__m128i a, __m128i b, int count)
+ /// PALIGNR xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<sbyte> AlignRight(Vector128<sbyte> left, Vector128<sbyte> right, byte mask) => AlignRight(left, right, mask);
+
+ /// <summary>
+ /// __m128i _mm_hadd_epi16 (__m128i a, __m128i b)
+ /// PHADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAdd(Vector128<short> left, Vector128<short> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m128i _mm_hadd_epi32 (__m128i a, __m128i b)
+ /// PHADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalAdd(Vector128<int> left, Vector128<int> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m128i _mm_hadds_epi16 (__m128i a, __m128i b)
+ /// PHADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAddSaturate(Vector128<short> left, Vector128<short> right) => HorizontalAddSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_hsub_epi16 (__m128i a, __m128i b)
+ /// PHSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtract(Vector128<short> left, Vector128<short> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m128i _mm_hsub_epi32 (__m128i a, __m128i b)
+ /// PHSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalSubtract(Vector128<int> left, Vector128<int> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m128i _mm_hsubs_epi16 (__m128i a, __m128i b)
+ /// PHSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtractSaturate(Vector128<short> left, Vector128<short> right) => HorizontalSubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_maddubs_epi16 (__m128i a, __m128i b)
+ /// PMADDUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyAddAdjacent(Vector128<byte> left, Vector128<sbyte> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mulhrs_epi16 (__m128i a, __m128i b)
+ /// PMULHRSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHighRoundScale(Vector128<short> left, Vector128<short> right) => MultiplyHighRoundScale(left, right);
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Shuffle(Vector128<sbyte> value, Vector128<sbyte> mask) => Shuffle(value, mask);
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Shuffle(Vector128<byte> value, Vector128<byte> mask) => Shuffle(value, mask);
+
+ /// <summary>
+ /// __m128i _mm_sign_epi8 (__m128i a, __m128i b)
+ /// PSIGNB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Sign(Vector128<sbyte> left, Vector128<sbyte> right) => Sign(left, right);
+ /// <summary>
+ /// __m128i _mm_sign_epi16 (__m128i a, __m128i b)
+ /// PSIGNW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Sign(Vector128<short> left, Vector128<short> right) => Sign(left, right);
+ /// <summary>
+ /// __m128i _mm_sign_epi32 (__m128i a, __m128i b)
+ /// PSIGND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Sign(Vector128<int> left, Vector128<int> right) => Sign(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs b/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs
new file mode 100644
index 000000000..a47aaf9ca
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs
@@ -0,0 +1,25 @@
+// 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.
+
+namespace System.Runtime.Remoting
+{
+ public class ObjectHandle : MarshalByRefObject
+ {
+ private object _wrappedObject;
+
+ private ObjectHandle()
+ {
+ }
+
+ public ObjectHandle(object o)
+ {
+ _wrappedObject = o;
+ }
+
+ public object Unwrap()
+ {
+ return _wrappedObject;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs
index 1c9c21eab..92c01ee30 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs
@@ -10,7 +10,7 @@ namespace System.Runtime.Serialization
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class SerializationException : SystemException
{
- private static String s_nullMessage = SR.SerializationException;
+ private static string s_nullMessage = SR.SerializationException;
// Creates a new SerializationException with its message
// string set to a default message.
@@ -20,13 +20,13 @@ namespace System.Runtime.Serialization
HResult = HResults.COR_E_SERIALIZATION;
}
- public SerializationException(String message)
+ public SerializationException(string message)
: base(message)
{
HResult = HResults.COR_E_SERIALIZATION;
}
- public SerializationException(String message, Exception innerException)
+ public SerializationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_SERIALIZATION;
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs
new file mode 100644
index 000000000..a97418963
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs
@@ -0,0 +1,515 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Runtime.Serialization
+{
+ /// <summary>The structure for holding all of the data needed for object serialization and deserialization.</summary>
+ public sealed class SerializationInfo
+ {
+ private const int DefaultSize = 4;
+
+ // Even though we have a dictionary, we're still keeping all the arrays around for back-compat.
+ // Otherwise we may run into potentially breaking behaviors like GetEnumerator() not returning entries in the same order they were added.
+ private string[] _names;
+ private object[] _values;
+ private Type[] _types;
+ private int _count;
+ private Dictionary<string, int> _nameToIndex;
+ private IFormatterConverter _converter;
+ private string _rootTypeName;
+ private string _rootTypeAssemblyName;
+ private Type _rootType;
+
+ [CLSCompliant(false)]
+ public SerializationInfo(Type type, IFormatterConverter converter)
+ {
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (converter == null)
+ {
+ throw new ArgumentNullException(nameof(converter));
+ }
+
+ _rootType = type;
+ _rootTypeName = type.FullName;
+ _rootTypeAssemblyName = type.Module.Assembly.FullName;
+
+ _names = new string[DefaultSize];
+ _values = new object[DefaultSize];
+ _types = new Type[DefaultSize];
+
+ _nameToIndex = new Dictionary<string, int>();
+
+ _converter = converter;
+ }
+
+ [CLSCompliant(false)]
+ public SerializationInfo(Type type, IFormatterConverter converter, bool requireSameTokenInPartialTrust)
+ : this(type, converter)
+ {
+ // requireSameTokenInPartialTrust is a vacuous parameter in a platform that does not support partial trust.
+ }
+
+ public string FullTypeName
+ {
+ get { return _rootTypeName; }
+ set
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ _rootTypeName = value;
+ IsFullTypeNameSetExplicit = true;
+ }
+ }
+
+ public string AssemblyName
+ {
+ get { return _rootTypeAssemblyName; }
+ set
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ _rootTypeAssemblyName = value;
+ IsAssemblyNameSetExplicit = true;
+ }
+ }
+
+ public bool IsFullTypeNameSetExplicit { get; private set; }
+
+ public bool IsAssemblyNameSetExplicit { get; private set; }
+
+ public void SetType(Type type)
+ {
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (!ReferenceEquals(_rootType, type))
+ {
+ _rootType = type;
+ _rootTypeName = type.FullName;
+ _rootTypeAssemblyName = type.Module.Assembly.FullName;
+ IsFullTypeNameSetExplicit = false;
+ IsAssemblyNameSetExplicit = false;
+ }
+ }
+
+ public int MemberCount => _count;
+
+ public Type ObjectType => _rootType;
+
+ public SerializationInfoEnumerator GetEnumerator() => new SerializationInfoEnumerator(_names, _values, _types, _count);
+
+ private void ExpandArrays()
+ {
+ int newSize;
+ Debug.Assert(_names.Length == _count, "[SerializationInfo.ExpandArrays]_names.Length == _count");
+
+ newSize = (_count * 2);
+
+ // In the pathological case, we may wrap
+ if (newSize < _count)
+ {
+ if (int.MaxValue > _count)
+ {
+ newSize = int.MaxValue;
+ }
+ }
+
+ // Allocate more space and copy the data
+ string[] newMembers = new string[newSize];
+ object[] newData = new object[newSize];
+ Type[] newTypes = new Type[newSize];
+
+ Array.Copy(_names, newMembers, _count);
+ Array.Copy(_values, newData, _count);
+ Array.Copy(_types, newTypes, _count);
+
+ // Assign the new arrays back to the member vars.
+ _names = newMembers;
+ _values = newData;
+ _types = newTypes;
+ }
+
+ public void AddValue(string name, object value, Type type)
+ {
+ if (null == name)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ AddValueInternal(name, value, type);
+ }
+
+ public void AddValue(string name, object value)
+ {
+ if (null == value)
+ {
+ AddValue(name, value, typeof(object));
+ }
+ else
+ {
+ AddValue(name, value, value.GetType());
+ }
+ }
+
+ public void AddValue(string name, bool value)
+ {
+ AddValue(name, (object)value, typeof(bool));
+ }
+
+ public void AddValue(string name, char value)
+ {
+ AddValue(name, (object)value, typeof(char));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(string name, sbyte value)
+ {
+ AddValue(name, (object)value, typeof(sbyte));
+ }
+
+ public void AddValue(string name, byte value)
+ {
+ AddValue(name, (object)value, typeof(byte));
+ }
+
+ public void AddValue(string name, short value)
+ {
+ AddValue(name, (object)value, typeof(short));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(string name, ushort value)
+ {
+ AddValue(name, (object)value, typeof(ushort));
+ }
+
+ public void AddValue(string name, int value)
+ {
+ AddValue(name, (object)value, typeof(int));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(string name, uint value)
+ {
+ AddValue(name, (object)value, typeof(uint));
+ }
+
+ public void AddValue(string name, long value)
+ {
+ AddValue(name, (object)value, typeof(long));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(string name, ulong value)
+ {
+ AddValue(name, (object)value, typeof(ulong));
+ }
+
+ public void AddValue(string name, float value)
+ {
+ AddValue(name, (object)value, typeof(float));
+ }
+
+ public void AddValue(string name, double value)
+ {
+ AddValue(name, (object)value, typeof(double));
+ }
+
+ public void AddValue(string name, decimal value)
+ {
+ AddValue(name, (object)value, typeof(decimal));
+ }
+
+ public void AddValue(string name, DateTime value)
+ {
+ AddValue(name, (object)value, typeof(DateTime));
+ }
+
+ internal void AddValueInternal(string name, object value, Type type)
+ {
+ if (_nameToIndex.ContainsKey(name))
+ {
+ throw new SerializationException(SR.Serialization_SameNameTwice);
+ }
+ _nameToIndex.Add(name, _count);
+
+ // If we need to expand the arrays, do so.
+ if (_count >= _names.Length)
+ {
+ ExpandArrays();
+ }
+
+ // Add the data and then advance the counter.
+ _names[_count] = name;
+ _values[_count] = value;
+ _types[_count] = type;
+ _count++;
+ }
+
+ /// <summary>
+ /// Finds the value if it exists in the current data. If it does, we replace
+ /// the values, if not, we append it to the end. This is useful to the
+ /// ObjectManager when it's performing fixups.
+ ///
+ /// All error checking is done with asserts. Although public in coreclr,
+ /// it's not exposed in a contract and is only meant to be used by corefx.
+ ///
+ /// This isn't a public API, but it gets invoked dynamically by
+ /// BinaryFormatter
+ ///
+ /// This should not be used by clients: exposing out this functionality would allow children
+ /// to overwrite their parent's values. It is public in order to give corefx access to it for
+ /// its ObjectManager implementation, but it should not be exposed out of a contract.
+ /// </summary>
+ /// <param name="name"> The name of the data to be updated.</param>
+ /// <param name="value"> The new value.</param>
+ /// <param name="type"> The type of the data being added.</param>
+ public void UpdateValue(string name, object value, Type type)
+ {
+ Debug.Assert(null != name, "[SerializationInfo.UpdateValue]name!=null");
+ Debug.Assert(null != value, "[SerializationInfo.UpdateValue]value!=null");
+ Debug.Assert(null != (object)type, "[SerializationInfo.UpdateValue]type!=null");
+
+ int index = FindElement(name);
+ if (index < 0)
+ {
+ AddValueInternal(name, value, type);
+ }
+ else
+ {
+ _values[index] = value;
+ _types[index] = type;
+ }
+ }
+
+ private int FindElement(string name)
+ {
+ if (null == name)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+ int index;
+ if (_nameToIndex.TryGetValue(name, out index))
+ {
+ return index;
+ }
+ return -1;
+ }
+
+ /// <summary>
+ /// Gets the location of a particular member and then returns
+ /// the value of the element at that location. The type of the member is
+ /// returned in the foundType field.
+ /// </summary>
+ /// <param name="name"> The name of the element to find.</param>
+ /// <param name="foundType"> The type of the element associated with the given name.</param>
+ /// <returns>The value of the element at the position associated with name.</returns>
+ private object GetElement(string name, out Type foundType)
+ {
+ int index = FindElement(name);
+ if (index == -1)
+ {
+ throw new SerializationException(SR.Format(SR.Serialization_NotFound, name));
+ }
+
+ Debug.Assert(index < _values.Length, "[SerializationInfo.GetElement]index<_values.Length");
+ Debug.Assert(index < _types.Length, "[SerializationInfo.GetElement]index<_types.Length");
+
+ foundType = _types[index];
+ Debug.Assert((object)foundType != null, "[SerializationInfo.GetElement]foundType!=null");
+ return _values[index];
+ }
+
+ private object GetElementNoThrow(string name, out Type foundType)
+ {
+ int index = FindElement(name);
+ if (index == -1)
+ {
+ foundType = null;
+ return null;
+ }
+
+ Debug.Assert(index < _values.Length, "[SerializationInfo.GetElement]index<_values.Length");
+ Debug.Assert(index < _types.Length, "[SerializationInfo.GetElement]index<_types.Length");
+
+ foundType = _types[index];
+ Debug.Assert((object)foundType != null, "[SerializationInfo.GetElement]foundType!=null");
+ return _values[index];
+ }
+
+ public object GetValue(string name, Type type)
+ {
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (!type.IsRuntimeImplemented())
+ throw new ArgumentException(SR.Argument_MustBeRuntimeType);
+ Type foundType;
+ object value;
+
+ value = GetElement(name, out foundType);
+
+ if (ReferenceEquals(foundType, type) || type.IsAssignableFrom(foundType) || value == null)
+ {
+ return value;
+ }
+
+ Debug.Assert(_converter != null, "[SerializationInfo.GetValue]_converter!=null");
+ return _converter.Convert(value, type);
+ }
+
+ internal object GetValueNoThrow(string name, Type type)
+ {
+ Type foundType;
+ object value;
+
+ Debug.Assert((object)type != null, "[SerializationInfo.GetValue]type ==null");
+ Debug.Assert(type.IsRuntimeImplemented(), "[SerializationInfo.GetValue]type is not a runtime type");
+
+ value = GetElementNoThrow(name, out foundType);
+ if (value == null)
+ return null;
+
+ if (ReferenceEquals(foundType, type) || type.IsAssignableFrom(foundType) || value == null)
+ {
+ return value;
+ }
+
+ Debug.Assert(_converter != null, "[SerializationInfo.GetValue]_converter!=null");
+
+ return _converter.Convert(value, type);
+ }
+
+ public bool GetBoolean(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(bool)) ? (bool)value : _converter.ToBoolean(value);
+ }
+
+ public char GetChar(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(char)) ? (char)value : _converter.ToChar(value);
+ }
+
+ [CLSCompliant(false)]
+ public sbyte GetSByte(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(sbyte)) ? (sbyte)value : _converter.ToSByte(value);
+ }
+
+ public byte GetByte(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(byte)) ? (byte)value : _converter.ToByte(value);
+ }
+
+ public short GetInt16(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(short)) ? (short)value : _converter.ToInt16(value);
+ }
+
+ [CLSCompliant(false)]
+ public ushort GetUInt16(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(ushort)) ? (ushort)value : _converter.ToUInt16(value);
+ }
+
+ public int GetInt32(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(int)) ? (int)value : _converter.ToInt32(value);
+ }
+
+ [CLSCompliant(false)]
+ public uint GetUInt32(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(uint)) ? (uint)value : _converter.ToUInt32(value);
+ }
+
+ public long GetInt64(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(long)) ? (long)value : _converter.ToInt64(value);
+ }
+
+ [CLSCompliant(false)]
+ public ulong GetUInt64(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(ulong)) ? (ulong)value : _converter.ToUInt64(value);
+ }
+
+ public float GetSingle(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(float)) ? (float)value : _converter.ToSingle(value);
+ }
+
+
+ public double GetDouble(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(double)) ? (double)value : _converter.ToDouble(value);
+ }
+
+ public decimal GetDecimal(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(decimal)) ? (decimal)value : _converter.ToDecimal(value);
+ }
+
+ public DateTime GetDateTime(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(DateTime)) ? (DateTime)value : _converter.ToDateTime(value);
+ }
+
+ public string GetString(string name)
+ {
+ Type foundType;
+ object value = GetElement(name, out foundType);
+ return ReferenceEquals(foundType, typeof(string)) || value == null ? (string)value : _converter.ToString(value);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs
index 639951073..ba84e6542 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs
@@ -7,11 +7,11 @@ using System.Diagnostics;
namespace System.Runtime.Serialization
{
- public struct SerializationEntry
+ public readonly struct SerializationEntry
{
- private string _name;
- private object _value;
- private Type _type;
+ private readonly string _name;
+ private readonly object _value;
+ private readonly Type _type;
internal SerializationEntry(string entryName, object entryValue, Type entryType)
{
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs
index a81906638..dcb14f0ef 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs
@@ -19,11 +19,11 @@ namespace System.Runtime.Versioning
[AttributeUsageAttribute(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class TargetFrameworkAttribute : Attribute
{
- private String _frameworkName; // A target framework moniker
- private String _frameworkDisplayName;
+ private string _frameworkName; // A target framework moniker
+ private string _frameworkDisplayName;
// The frameworkName parameter is intended to be the string form of a FrameworkName instance.
- public TargetFrameworkAttribute(String frameworkName)
+ public TargetFrameworkAttribute(string frameworkName)
{
if (frameworkName == null)
throw new ArgumentNullException(nameof(frameworkName));
@@ -32,12 +32,12 @@ namespace System.Runtime.Versioning
// The target framework moniker that this assembly was compiled against.
// Use the FrameworkName class to interpret target framework monikers.
- public String FrameworkName
+ public string FrameworkName
{
get { return _frameworkName; }
}
- public String FrameworkDisplayName
+ public string FrameworkDisplayName
{
get { return _frameworkDisplayName; }
set { _frameworkDisplayName = value; }
diff --git a/src/System.Private.CoreLib/shared/System/SByte.cs b/src/System.Private.CoreLib/shared/System/SByte.cs
index c7cee2adc..e347e3b32 100644
--- a/src/System.Private.CoreLib/shared/System/SByte.cs
+++ b/src/System.Private.CoreLib/shared/System/SByte.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[CLSCompliant(false)] [StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct SByte : IComparable, IConvertible, IFormattable, IComparable<SByte>, IEquatable<SByte>, ISpanFormattable
+ public readonly struct SByte : IComparable, IConvertible, IFormattable, IComparable<sbyte>, IEquatable<sbyte>, ISpanFormattable
{
- private sbyte m_value; // Do not rename (binary serialization)
+ private readonly sbyte m_value; // Do not rename (binary serialization)
// The maximum value that a Byte may represent: 127.
public const sbyte MaxValue = (sbyte)0x7F;
@@ -29,36 +29,36 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type SByte, this method throws an ArgumentException.
//
- public int CompareTo(Object obj)
+ public int CompareTo(object obj)
{
if (obj == null)
{
return 1;
}
- if (!(obj is SByte))
+ if (!(obj is sbyte))
{
throw new ArgumentException(SR.Arg_MustBeSByte);
}
- return m_value - ((SByte)obj).m_value;
+ return m_value - ((sbyte)obj).m_value;
}
- public int CompareTo(SByte value)
+ public int CompareTo(sbyte value)
{
return m_value - value;
}
// Determines whether two Byte objects are equal.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is SByte))
+ if (!(obj is sbyte))
{
return false;
}
- return m_value == ((SByte)obj).m_value;
+ return m_value == ((sbyte)obj).m_value;
}
[NonVersionable]
- public bool Equals(SByte obj)
+ public bool Equals(sbyte obj)
{
return m_value == obj;
}
@@ -71,22 +71,22 @@ namespace System
// Provides a string representation of a byte.
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return ToString(format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x'))
{
@@ -107,14 +107,14 @@ namespace System
}
[CLSCompliant(false)]
- public static sbyte Parse(String s)
+ public static sbyte Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static sbyte Parse(String s, NumberStyles style)
+ public static sbyte Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -122,7 +122,7 @@ namespace System
}
[CLSCompliant(false)]
- public static sbyte Parse(String s, IFormatProvider provider)
+ public static sbyte Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -133,7 +133,7 @@ namespace System
// NumberFormatInfo is assumed.
//
[CLSCompliant(false)]
- public static sbyte Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static sbyte Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -147,7 +147,7 @@ namespace System
return Parse(s, style, NumberFormatInfo.GetInstance(provider));
}
- private static sbyte Parse(String s, NumberStyles style, NumberFormatInfo info)
+ private static sbyte Parse(string s, NumberStyles style, NumberFormatInfo info)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, style, info);
@@ -167,7 +167,7 @@ namespace System
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || i > Byte.MaxValue)
+ if ((i < 0) || i > byte.MaxValue)
{
throw new OverflowException(SR.Overflow_SByte);
}
@@ -179,7 +179,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, out SByte result)
+ public static bool TryParse(string s, out sbyte result)
{
if (s == null)
{
@@ -197,7 +197,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out SByte result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out sbyte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -217,7 +217,7 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out SByte result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out sbyte result)
{
result = 0;
int i;
@@ -228,7 +228,7 @@ namespace System
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || i > Byte.MaxValue)
+ if ((i < 0) || i > byte.MaxValue)
{
return false;
}
@@ -314,7 +314,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -324,7 +324,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "SByte", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs b/src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs
new file mode 100644
index 000000000..729e2f6b5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs
@@ -0,0 +1,42 @@
+// 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 Microsoft.Win32;
+
+namespace System.Security.AccessControl
+{
+ // We derived this enum from the definitions of KEY_READ and such from
+ // winnt.h and from MSDN, plus some experimental validation with regedit.
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/registry_key_security_and_access_rights.asp
+ [Flags]
+#if REGISTRY_ASSEMBLY
+ public
+#else
+ internal
+#endif
+ enum RegistryRights
+ {
+ // No None field - An ACE with the value 0 cannot grant nor deny.
+ QueryValues = Interop.Advapi32.RegistryOperations.KEY_QUERY_VALUE, // 0x0001 query the values of a registry key
+ SetValue = Interop.Advapi32.RegistryOperations.KEY_SET_VALUE, // 0x0002 create, delete, or set a registry value
+ CreateSubKey = Interop.Advapi32.RegistryOperations.KEY_CREATE_SUB_KEY, // 0x0004 required to create a subkey of a specific key
+ EnumerateSubKeys = Interop.Advapi32.RegistryOperations.KEY_ENUMERATE_SUB_KEYS, // 0x0008 required to enumerate sub keys of a key
+ Notify = Interop.Advapi32.RegistryOperations.KEY_NOTIFY, // 0x0010 needed to request change notifications
+ CreateLink = Interop.Advapi32.RegistryOperations.KEY_CREATE_LINK, // 0x0020 reserved for system use
+ ///
+ /// The Windows Kernel team agrees that it was a bad design to expose the WOW64_n options as permissions.
+ /// in the .NET Framework these options are exposed via the RegistryView enum
+ ///
+ /// Reg64 = Interop.Advapi32.RegistryOptions.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
+ /// Reg32 = Interop.Advapi32.RegistryOptions.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
+ ExecuteKey = ReadKey,
+ ReadKey = Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_READ | QueryValues | EnumerateSubKeys | Notify,
+ WriteKey = Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_WRITE | SetValue | CreateSubKey,
+ Delete = 0x10000,
+ ReadPermissions = 0x20000,
+ ChangePermissions = 0x40000,
+ TakeOwnership = 0x80000,
+ FullControl = 0xF003F | Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_READ | Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_WRITE
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs b/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs
index 227fed3fc..bc93fecef 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs
@@ -50,7 +50,7 @@ namespace System.Security
internal unsafe uint Length => Interop.OleAut32.SysStringLen(this);
- internal unsafe static void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy)
+ internal static unsafe void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy)
{
if (bytesToCopy == 0)
{
diff --git a/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs b/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs
index cfeebc1da..ad14bcd29 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs
@@ -70,14 +70,6 @@ namespace System.Security
}
}
- private void EnsureNotDisposed()
- {
- if (_buffer == null)
- {
- throw new ObjectDisposedException(GetType().Name);
- }
- }
-
private void ClearCore()
{
_decryptedLength = 0;
@@ -143,7 +135,7 @@ namespace System.Security
_buffer.Write((ulong)(index * sizeof(char)), c);
}
- internal unsafe IntPtr MarshalToBSTR()
+ internal unsafe IntPtr MarshalToBSTRCore()
{
int length = _decryptedLength;
IntPtr ptr = IntPtr.Zero;
diff --git a/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs b/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs
index 2a8008191..a78fbc222 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs
@@ -6,7 +6,6 @@ using System.Diagnostics;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
-using Microsoft.Win32;
namespace System.Security
{
@@ -145,7 +144,7 @@ namespace System.Security
}
}
- internal unsafe IntPtr MarshalToBSTR()
+ internal unsafe IntPtr MarshalToBSTRCore()
{
int length = _decryptedLength;
IntPtr ptr = IntPtr.Zero;
@@ -232,14 +231,6 @@ namespace System.Security
return result;
}
- private void EnsureNotDisposed()
- {
- if (_buffer == null)
- {
- throw new ObjectDisposedException(GetType().Name);
- }
- }
-
// -----------------------------
// ---- PAL layer ends here ----
// -----------------------------
diff --git a/src/System.Private.CoreLib/shared/System/Security/SecureString.cs b/src/System.Private.CoreLib/shared/System/Security/SecureString.cs
index 22f15acca..cdee9c907 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SecureString.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SecureString.cs
@@ -139,7 +139,7 @@ namespace System.Security
{
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexString);
}
- Debug.Assert(index <= Int32.MaxValue / sizeof(char));
+ Debug.Assert(index <= int.MaxValue / sizeof(char));
EnsureNotDisposed();
EnsureNotReadOnly();
@@ -156,6 +156,23 @@ namespace System.Security
}
}
+ private void EnsureNotDisposed()
+ {
+ if (_buffer == null)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ internal IntPtr MarshalToBSTR()
+ {
+ lock (_methodLock)
+ {
+ EnsureNotDisposed();
+ return MarshalToBSTRCore();
+ }
+ }
+
internal unsafe IntPtr MarshalToString(bool globalAlloc, bool unicode)
{
lock (_methodLock)
diff --git a/src/System.Private.CoreLib/shared/System/Single.cs b/src/System.Private.CoreLib/shared/System/Single.cs
index 7bffa1ac7..8d1788f73 100644
--- a/src/System.Private.CoreLib/shared/System/Single.cs
+++ b/src/System.Private.CoreLib/shared/System/Single.cs
@@ -23,9 +23,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Single : IComparable, IConvertible, IFormattable, IComparable<Single>, IEquatable<Single>, ISpanFormattable
+ public readonly struct Single : IComparable, IConvertible, IFormattable, IComparable<float>, IEquatable<float>, ISpanFormattable
{
- private float m_value; // Do not rename (binary serialization)
+ private readonly float m_value; // Do not rename (binary serialization)
//
// Public constants
@@ -52,7 +52,7 @@ namespace System
/// <summary>Determines whether the specified value is infinite.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsInfinity(float f)
+ public static unsafe bool IsInfinity(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
return (bits & 0x7FFFFFFF) == 0x7F800000;
@@ -61,7 +61,7 @@ namespace System
/// <summary>Determines whether the specified value is NaN.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNaN(float f)
+ public static unsafe bool IsNaN(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
return (bits & 0x7FFFFFFF) > 0x7F800000;
@@ -70,16 +70,15 @@ namespace System
/// <summary>Determines whether the specified value is negative.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNegative(float f)
+ public static unsafe bool IsNegative(float f)
{
- var bits = unchecked((uint)BitConverter.SingleToInt32Bits(f));
- return (bits & 0x80000000) == 0x80000000;
+ return BitConverter.SingleToInt32Bits(f) < 0;
}
/// <summary>Determines whether the specified value is negative infinity.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNegativeInfinity(float f)
+ public static unsafe bool IsNegativeInfinity(float f)
{
return (f == float.NegativeInfinity);
}
@@ -87,7 +86,7 @@ namespace System
/// <summary>Determines whether the specified value is normal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsNormal(float f)
+ public static unsafe bool IsNormal(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
bits &= 0x7FFFFFFF;
@@ -97,7 +96,7 @@ namespace System
/// <summary>Determines whether the specified value is positive infinity.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsPositiveInfinity(float f)
+ public static unsafe bool IsPositiveInfinity(float f)
{
return (f == float.PositiveInfinity);
}
@@ -105,7 +104,7 @@ namespace System
/// <summary>Determines whether the specified value is subnormal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsSubnormal(float f)
+ public static unsafe bool IsSubnormal(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
bits &= 0x7FFFFFFF;
@@ -118,13 +117,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Single, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Single)
+ if (value is float)
{
float f = (float)value;
if (m_value < f) return -1;
@@ -141,7 +140,7 @@ namespace System
}
- public int CompareTo(Single value)
+ public int CompareTo(float value)
{
if (m_value < value) return -1;
if (m_value > value) return 1;
@@ -155,48 +154,48 @@ namespace System
}
[NonVersionable]
- public static bool operator ==(Single left, Single right)
+ public static bool operator ==(float left, float right)
{
return left == right;
}
[NonVersionable]
- public static bool operator !=(Single left, Single right)
+ public static bool operator !=(float left, float right)
{
return left != right;
}
[NonVersionable]
- public static bool operator <(Single left, Single right)
+ public static bool operator <(float left, float right)
{
return left < right;
}
[NonVersionable]
- public static bool operator >(Single left, Single right)
+ public static bool operator >(float left, float right)
{
return left > right;
}
[NonVersionable]
- public static bool operator <=(Single left, Single right)
+ public static bool operator <=(float left, float right)
{
return left <= right;
}
[NonVersionable]
- public static bool operator >=(Single left, Single right)
+ public static bool operator >=(float left, float right)
{
return left >= right;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Single))
+ if (!(obj is float))
{
return false;
}
- float temp = ((Single)obj).m_value;
+ float temp = ((float)obj).m_value;
if (temp == m_value)
{
return true;
@@ -205,7 +204,7 @@ namespace System
return IsNaN(temp) && IsNaN(m_value);
}
- public bool Equals(Single obj)
+ public bool Equals(float obj)
{
if (obj == m_value)
{
@@ -217,7 +216,7 @@ namespace System
public override int GetHashCode()
{
- var bits = Unsafe.As<float, int>(ref m_value);
+ var bits = Unsafe.As<float, int>(ref Unsafe.AsRef(in m_value));
// Optimized check for IsNan() || IsZero()
if (((bits - 1) & 0x7FFFFFFF) >= 0x7F800000)
@@ -229,22 +228,22 @@ namespace System
return bits;
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatSingle(m_value, null, NumberFormatInfo.CurrentInfo);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatSingle(m_value, null, NumberFormatInfo.GetInstance(provider));
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatSingle(m_value, format, NumberFormatInfo.CurrentInfo);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider));
}
@@ -262,39 +261,39 @@ namespace System
// PositiveInfinity or NegativeInfinity for a number that is too
// large or too small.
//
- public static float Parse(String s)
+ public static float Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}
- public static float Parse(String s, NumberStyles style)
+ public static float Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, style, NumberFormatInfo.CurrentInfo);
}
- public static float Parse(String s, IFormatProvider provider)
+ public static float Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}
- public static float Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static float Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static float Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ public static float Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Float | NumberStyles.AllowThousands, IFormatProvider provider = null)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Number.ParseSingle(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static Boolean TryParse(String s, out Single result)
+ public static bool TryParse(string s, out float result)
{
if (s == null)
{
@@ -310,7 +309,7 @@ namespace System
return TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
}
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Single result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out float result)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
@@ -329,21 +328,21 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static Boolean TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Single result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out float result)
{
bool success = Number.TryParseSingle(s, style, info, out result);
if (!success)
{
ReadOnlySpan<char> sTrim = s.Trim();
- if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
result = PositiveInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ else if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
result = NegativeInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ else if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
result = NaN;
}
@@ -425,7 +424,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -435,7 +434,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Single", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Span.Fast.cs b/src/System.Private.CoreLib/shared/System/Span.Fast.cs
index 0ae1922fd..b3cfc8daf 100644
--- a/src/System.Private.CoreLib/shared/System/Span.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/Span.Fast.cs
@@ -2,10 +2,11 @@
// 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.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
+using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
using Internal.Runtime.CompilerServices;
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -22,8 +23,6 @@ namespace System
/// Span represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
- [DebuggerTypeProxy(typeof(SpanDebugView<>))]
- [DebuggerDisplay("{ToString(),raw}")]
[NonVersionable]
public readonly ref partial struct Span<T>
{
@@ -155,6 +154,13 @@ namespace System
}
/// <summary>
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
+ /// It can be used for pinning and is required to support the use of span within a fixed statement.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe ref T GetPinnableReference() => ref (_length != 0) ? ref _pointer.Value : ref Unsafe.AsRef<T>(null);
+
+ /// <summary>
/// Clears the contents of this span.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -232,6 +238,7 @@ namespace System
/// <exception cref="System.ArgumentException">
/// Thrown when the destination Span is shorter than the source Span.
/// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Span<T> destination)
{
// Using "if (!TryCopyTo(...))" results in two branches: one for the length
@@ -283,7 +290,7 @@ namespace System
/// <summary>
/// For <see cref="Span{Char}"/>, returns a new instance of string that represents the characters pointed to by the span.
- /// Otherwise, returns a <see cref="String"/> with the name of the type and the number of elements.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
/// </summary>
public override string ToString()
{
diff --git a/src/System.Private.CoreLib/shared/System/Span.cs b/src/System.Private.CoreLib/shared/System/Span.cs
index 78733515c..185042fb5 100644
--- a/src/System.Private.CoreLib/shared/System/Span.cs
+++ b/src/System.Private.CoreLib/shared/System/Span.cs
@@ -5,9 +5,8 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
-#if !FEATURE_PORTABLE_SPAN
+
using System.Runtime.Versioning;
-#endif // !FEATURE_PORTABLE_SPAN
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -26,9 +25,7 @@ namespace System
/// </summary>
public int Length
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
return _length;
@@ -40,12 +37,11 @@ namespace System
/// </summary>
public bool IsEmpty
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
- return _length == 0;
+ // Workaround for https://github.com/dotnet/coreclr/issues/19620
+ return 0 >= (uint)_length;
}
}
@@ -89,13 +85,13 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Span{T}"/>
/// </summary>
- public static implicit operator Span<T>(ArraySegment<T> arraySegment)
- => new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator Span<T>(ArraySegment<T> segment)
+ => new Span<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Returns an empty <see cref="Span{T}"/>
/// </summary>
- public static Span<T> Empty => default(Span<T>);
+ public static Span<T> Empty => default;
/// <summary>Gets an enumerator for this span.</summary>
public Enumerator GetEnumerator() => new Enumerator(this);
diff --git a/src/System.Private.CoreLib/shared/System/SpanDebugView.cs b/src/System.Private.CoreLib/shared/System/SpanDebugView.cs
index caa12ef9e..f79c67306 100644
--- a/src/System.Private.CoreLib/shared/System/SpanDebugView.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanDebugView.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Reflection;
-using System.Runtime.CompilerServices;
namespace System
{
@@ -14,7 +12,7 @@ namespace System
public SpanDebugView(Span<T> span)
{
- _array = span.ToArray();
+ _array = span.ToArray();
}
public SpanDebugView(ReadOnlySpan<T> span)
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs
index 656b864e2..2aec70409 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs
@@ -6,9 +6,7 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
namespace System
{
@@ -26,7 +24,7 @@ namespace System
}
public static int BinarySearch<T, TComparable>(
- ref T spanStart, int length, TComparable comparable)
+ ref T spanStart, int length, TComparable comparable)
where TComparable : IComparable<T>
{
int lo = 0;
@@ -64,11 +62,11 @@ namespace System
}
// Helper to allow sharing all code via IComparable<T> inlineable
- internal struct ComparerComparable<T, TComparer> : IComparable<T>
+ internal readonly struct ComparerComparable<T, TComparer> : IComparable<T>
where TComparer : IComparer<T>
{
- readonly T _value;
- readonly TComparer _comparer;
+ private readonly T _value;
+ private readonly TComparer _comparer;
public ComparerComparable(T value, TComparer comparer)
{
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
index 860b2efa0..373065363 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
@@ -4,18 +4,19 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Numerics;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
-#if !netstandard11
-using System.Numerics;
-#endif
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif // BIT64
namespace System
{
- internal static partial class SpanHelpers
+ internal static partial class SpanHelpers // .Byte
{
public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
{
@@ -70,7 +71,8 @@ namespace System
// Reduce space for search, cause we don't care if we find the search value after the index of a previously found value
searchSpaceLength = tempIndex;
- if (index == 0) break;
+ if (index == 0)
+ break;
}
}
return index;
@@ -88,48 +90,137 @@ namespace System
for (int i = 0; i < valueLength; i++)
{
var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
- if (tempIndex > index) index = tempIndex;
+ if (tempIndex > index)
+ index = tempIndex;
}
return index;
}
- public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
+ // Adapted from IndexOf(...)
+ public static unsafe bool Contains(ref byte searchSpace, byte value, int length)
{
Debug.Assert(length >= 0);
-
+
uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ }
+
+ SequentialScan:
+ while ((byte*)nLength >= (byte*)8)
+ {
+ nLength -= 8;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 0) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
+ {
+ goto Found;
+ }
+
+ index += 8;
+ }
+
+ if ((byte*)nLength >= (byte*)4)
+ {
+ nLength -= 4;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 0) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
+ {
+ goto Found;
+ }
+
+ index += 4;
+ }
+
+ while ((byte*)nLength > (byte*)0)
+ {
+ nLength -= 1;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
+ goto Found;
+
+ index += 1;
+ }
+
+ if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
+ {
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
+ // Get comparison Vector
+ Vector<byte> vComparison = new Vector<byte>(value);
+
+ while ((byte*)nLength > (byte*)index)
{
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index)));
+ if (Vector<byte>.Zero.Equals(vMatches))
+ {
+ index += Vector<byte>.Count;
+ continue;
+ }
+
+ goto Found;
+ }
+
+ if ((int)(byte*)index < length)
+ {
+ nLength = (IntPtr)(length - (int)(byte*)index);
+ goto SequentialScan;
}
}
+
+ return false;
+
+ Found:
+ return true;
+ }
+
+ public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
+ {
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ }
SequentialScan:
-#endif
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 4))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4))
goto Found4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 5))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5))
goto Found5;
- if (uValue == Unsafe.Add(ref searchSpace, index + 6))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6))
goto Found6;
- if (uValue == Unsafe.Add(ref searchSpace, index + 7))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
goto Found7;
index += 8;
@@ -139,13 +230,13 @@ namespace System
{
nLength -= 4;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
index += 4;
@@ -155,17 +246,19 @@ namespace System
{
nLength -= 1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> vComparison = GetVector(value);
+ Vector<byte> vComparison = new Vector<byte>(value);
+
while ((byte*)nLength > (byte*)index)
{
var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index)));
@@ -180,14 +273,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -246,39 +335,35 @@ namespace System
Debug.Assert(length >= 0);
uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- if (uValue == Unsafe.Add(ref searchSpace, index + 7))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
goto Found7;
- if (uValue == Unsafe.Add(ref searchSpace, index + 6))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6))
goto Found6;
- if (uValue == Unsafe.Add(ref searchSpace, index + 5))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5))
goto Found5;
- if (uValue == Unsafe.Add(ref searchSpace, index + 4))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4))
goto Found4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
@@ -287,13 +372,13 @@ namespace System
nLength -= 4;
index -= 4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
@@ -302,16 +387,17 @@ namespace System
nLength -= 1;
index -= 1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
// Get comparison Vector
- Vector<byte> vComparison = GetVector(value);
+ Vector<byte> vComparison = new Vector<byte>(value);
+
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index - Vector<byte>.Count)));
@@ -322,15 +408,14 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -356,46 +441,42 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found7;
@@ -406,16 +487,16 @@ namespace System
{
nLength -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
@@ -426,19 +507,20 @@ namespace System
{
nLength -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
while ((byte*)nLength > (byte*)index)
{
@@ -457,14 +539,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -491,46 +569,42 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found7;
@@ -541,16 +615,16 @@ namespace System
{
nLength -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
@@ -561,20 +635,22 @@ namespace System
{
nLength -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
- Vector<byte> values2 = GetVector(value2);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
+ Vector<byte> values2 = new Vector<byte>(value2);
+
while ((byte*)nLength > (byte*)index)
{
Vector<byte> vData = Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index));
@@ -596,14 +672,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -629,47 +701,43 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found7;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
@@ -679,16 +747,16 @@ namespace System
nLength -= 4;
index -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
@@ -698,17 +766,18 @@ namespace System
nLength -= 1;
index -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
@@ -723,16 +792,15 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -759,47 +827,43 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found7;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
@@ -809,16 +873,16 @@ namespace System
nLength -= 4;
index -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
@@ -828,18 +892,20 @@ namespace System
nLength -= 1;
index -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
- Vector<byte> values2 = GetVector(value2);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
+ Vector<byte> values2 = new Vector<byte>(value2);
+
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
Vector<byte> vData = Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index - Vector<byte>.Count));
@@ -857,16 +923,15 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -886,17 +951,16 @@ namespace System
return (int)(byte*)(index + 7);
}
- public static unsafe bool SequenceEqual(ref byte first, ref byte second, int length)
+ // Optimized byte-based SequenceEquals. The "length" parameter for this one is declared a nuint rather than int as we also use it for types other than byte
+ // where the length can exceed 2Gb once scaled by sizeof(T).
+ public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint length)
{
- Debug.Assert(length >= 0);
-
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
- IntPtr i = (IntPtr)0; // Use IntPtr and byte* for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr n = (IntPtr)length;
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr n = (IntPtr)(void*)length;
-#if !netstandard11
if (Vector.IsHardwareAccelerated && (byte*)n >= (byte*)Vector<byte>.Count)
{
n -= Vector<byte>.Count;
@@ -912,7 +976,6 @@ namespace System
return Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref first, n)) ==
Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref second, n));
}
-#endif
if ((byte*)n >= (byte*)sizeof(UIntPtr))
{
@@ -944,7 +1007,6 @@ namespace System
return false;
}
-#if !netstandard11
// Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateFirstFoundByte(Vector<byte> match)
@@ -965,7 +1027,6 @@ namespace System
// Single LEA instruction with jitted const (using function result)
return i * 8 + LocateFirstFoundByte(candidate);
}
-#endif
public static unsafe int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength)
{
@@ -975,13 +1036,11 @@ namespace System
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
- var minLength = firstLength;
- if (minLength > secondLength) minLength = secondLength;
+ IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
- IntPtr i = (IntPtr)0; // Use IntPtr and byte* for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr n = (IntPtr)minLength;
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr n = (IntPtr)(void*)minLength;
-#if !netstandard11
if (Vector.IsHardwareAccelerated && (byte*)n > (byte*)Vector<byte>.Count)
{
n -= Vector<byte>.Count;
@@ -996,7 +1055,6 @@ namespace System
}
goto NotEqual;
}
-#endif
if ((byte*)n > (byte*)sizeof(UIntPtr))
{
@@ -1013,10 +1071,11 @@ namespace System
}
NotEqual: // Workaround for https://github.com/dotnet/coreclr/issues/13549
- while((byte*)minLength > (byte*)i)
+ while ((byte*)minLength > (byte*)i)
{
int result = Unsafe.AddByteOffset(ref first, i).CompareTo(Unsafe.AddByteOffset(ref second, i));
- if (result != 0) return result;
+ if (result != 0)
+ return result;
i += 1;
}
@@ -1024,7 +1083,6 @@ namespace System
return firstLength - secondLength;
}
-#if !netstandard11
// Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(Vector<byte> match)
@@ -1045,23 +1103,16 @@ namespace System
// Single LEA instruction with jitted const (using function result)
return i * 8 + LocateLastFoundByte(candidate);
}
-#endif
-#if !netstandard11
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateFirstFoundByte(ulong match)
{
- unchecked
- {
- // Flag least significant power of two bit
- var powerOfTwoFlag = match ^ (match - 1);
- // Shift all powers of two into the high byte and extract
- return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57);
- }
+ // Flag least significant power of two bit
+ var powerOfTwoFlag = match ^ (match - 1);
+ // Shift all powers of two into the high byte and extract
+ return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57);
}
-#endif
-#if !netstandard11
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(ulong match)
{
@@ -1074,24 +1125,7 @@ namespace System
}
return index;
}
-#endif
-
-#if !netstandard11
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Vector<byte> GetVector(byte vectorByte)
- {
-#if !netcoreapp
- // Vector<byte> .ctor doesn't become an intrinsic due to detection issue
- // However this does cause it to become an intrinsic (with additional multiply and reg->reg copy)
- // https://github.com/dotnet/coreclr/issues/7459#issuecomment-253965670
- return Vector.AsVectorByte(new Vector<uint>(vectorByte * 0x01010101u));
-#else
- return new Vector<byte>(vectorByte);
-#endif
- }
-#endif
-#if !netstandard11
private const ulong XorPowerOfTwoToHighByte = (0x07ul |
0x06ul << 8 |
0x05ul << 16 |
@@ -1099,6 +1133,5 @@ namespace System
0x03ul << 32 |
0x02ul << 40 |
0x01ul << 48) + 1;
-#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs
new file mode 100644
index 000000000..02df69feb
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs
@@ -0,0 +1,420 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Numerics;
+
+#if !netstandard
+using Internal.Runtime.CompilerServices;
+#endif
+
+namespace System
+{
+ internal static partial class SpanHelpers // .Char
+ {
+ public static unsafe int SequenceCompareTo(ref char first, int firstLength, ref char second, int secondLength)
+ {
+ Debug.Assert(firstLength >= 0);
+ Debug.Assert(secondLength >= 0);
+
+ int lengthDelta = firstLength - secondLength;
+
+ if (Unsafe.AreSame(ref first, ref second))
+ goto Equal;
+
+ IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+
+ if ((byte*)minLength >= (byte*)(sizeof(UIntPtr) / sizeof(char)))
+ {
+ if (Vector.IsHardwareAccelerated && (byte*)minLength >= (byte*)Vector<ushort>.Count)
+ {
+ IntPtr nLength = minLength - Vector<ushort>.Count;
+ do
+ {
+ if (Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
+ Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+ {
+ break;
+ }
+ i += Vector<ushort>.Count;
+ }
+ while ((byte*)nLength >= (byte*)i);
+ }
+
+ while ((byte*)minLength >= (byte*)(i + sizeof(UIntPtr) / sizeof(char)))
+ {
+ if (Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
+ Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+ {
+ break;
+ }
+ i += sizeof(UIntPtr) / sizeof(char);
+ }
+ }
+
+ if (sizeof(UIntPtr) > sizeof(int) && (byte*)minLength >= (byte*)(i + sizeof(int) / sizeof(char)))
+ {
+ if (Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) ==
+ Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+ {
+ i += sizeof(int) / sizeof(char);
+ }
+ }
+
+ while ((byte*)i < (byte*)minLength)
+ {
+ int result = Unsafe.Add(ref first, i).CompareTo(Unsafe.Add(ref second, i));
+ if (result != 0)
+ return result;
+ i += 1;
+ }
+
+ Equal:
+ return lengthDelta;
+ }
+
+ // Adapted from IndexOf(...)
+ public static unsafe bool Contains(ref char searchSpace, char value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ fixed (char* pChars = &searchSpace)
+ {
+ char* pCh = pChars;
+ char* pEndCh = pCh + length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<ushort>.Count * 2)
+ {
+ // Figure out how many characters to read sequentially until we are vector aligned
+ // This is equivalent to:
+ // unaligned = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / elementsPerByte
+ // length = (Vector<ushort>.Count - unaligned) % Vector<ushort>.Count
+ const int elementsPerByte = sizeof(ushort) / sizeof(byte);
+ int unaligned = ((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) / elementsPerByte;
+ length = (Vector<ushort>.Count - unaligned) & (Vector<ushort>.Count - 1);
+ }
+
+ SequentialScan:
+ while (length >= 4)
+ {
+ length -= 4;
+
+ if (value == *pCh ||
+ value == *(pCh + 1) ||
+ value == *(pCh + 2) ||
+ value == *(pCh + 3))
+ {
+ goto Found;
+ }
+
+ pCh += 4;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+
+ if (value == *pCh)
+ goto Found;
+
+ pCh += 1;
+ }
+
+ // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow
+ // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
+ if (Vector.IsHardwareAccelerated && pCh < pEndCh)
+ {
+ // Get the highest multiple of Vector<ushort>.Count that is within the search space.
+ // That will be how many times we iterate in the loop below.
+ // This is equivalent to: length = Vector<ushort>.Count * ((int)(pEndCh - pCh) / Vector<ushort>.Count)
+ length = (int)((pEndCh - pCh) & ~(Vector<ushort>.Count - 1));
+
+ // Get comparison Vector
+ Vector<ushort> vComparison = new Vector<ushort>(value);
+
+ while (length > 0)
+ {
+ // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh is always vector aligned
+ Debug.Assert(((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) == 0);
+ Vector<ushort> vMatches = Vector.Equals(vComparison, Unsafe.Read<Vector<ushort>>(pCh));
+ if (Vector<ushort>.Zero.Equals(vMatches))
+ {
+ pCh += Vector<ushort>.Count;
+ length -= Vector<ushort>.Count;
+ continue;
+ }
+
+ goto Found;
+ }
+
+ if (pCh < pEndCh)
+ {
+ length = (int)(pEndCh - pCh);
+ goto SequentialScan;
+ }
+ }
+
+ return false;
+
+ Found:
+ return true;
+ }
+ }
+
+ public static unsafe int IndexOf(ref char searchSpace, char value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ fixed (char* pChars = &searchSpace)
+ {
+ char* pCh = pChars;
+ char* pEndCh = pCh + length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<ushort>.Count * 2)
+ {
+ // Figure out how many characters to read sequentially until we are vector aligned
+ // This is equivalent to:
+ // unaligned = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / elementsPerByte
+ // length = (Vector<ushort>.Count - unaligned) % Vector<ushort>.Count
+ const int elementsPerByte = sizeof(ushort) / sizeof(byte);
+ int unaligned = ((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) / elementsPerByte;
+ length = (Vector<ushort>.Count - unaligned) & (Vector<ushort>.Count - 1);
+ }
+
+ SequentialScan:
+ while (length >= 4)
+ {
+ length -= 4;
+
+ if (*pCh == value)
+ goto Found;
+ if (*(pCh + 1) == value)
+ goto Found1;
+ if (*(pCh + 2) == value)
+ goto Found2;
+ if (*(pCh + 3) == value)
+ goto Found3;
+
+ pCh += 4;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+
+ if (*pCh == value)
+ goto Found;
+
+ pCh += 1;
+ }
+
+ // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow
+ // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
+ if (Vector.IsHardwareAccelerated && pCh < pEndCh)
+ {
+ // Get the highest multiple of Vector<ushort>.Count that is within the search space.
+ // That will be how many times we iterate in the loop below.
+ // This is equivalent to: length = Vector<ushort>.Count * ((int)(pEndCh - pCh) / Vector<ushort>.Count)
+ length = (int)((pEndCh - pCh) & ~(Vector<ushort>.Count - 1));
+
+ // Get comparison Vector
+ Vector<ushort> vComparison = new Vector<ushort>(value);
+
+ while (length > 0)
+ {
+ // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh is always vector aligned
+ Debug.Assert(((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) == 0);
+ Vector<ushort> vMatches = Vector.Equals(vComparison, Unsafe.Read<Vector<ushort>>(pCh));
+ if (Vector<ushort>.Zero.Equals(vMatches))
+ {
+ pCh += Vector<ushort>.Count;
+ length -= Vector<ushort>.Count;
+ continue;
+ }
+ // Find offset of first match
+ return (int)(pCh - pChars) + LocateFirstFoundChar(vMatches);
+ }
+
+ if (pCh < pEndCh)
+ {
+ length = (int)(pEndCh - pCh);
+ goto SequentialScan;
+ }
+ }
+
+ return -1;
+ Found3:
+ pCh++;
+ Found2:
+ pCh++;
+ Found1:
+ pCh++;
+ Found:
+ return (int)(pCh - pChars);
+ }
+ }
+
+ public static unsafe int LastIndexOf(ref char searchSpace, char value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ fixed (char* pChars = &searchSpace)
+ {
+ char* pCh = pChars + length;
+ char* pEndCh = pChars;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<ushort>.Count * 2)
+ {
+ // Figure out how many characters to read sequentially from the end until we are vector aligned
+ // This is equivalent to: length = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / elementsPerByte
+ const int elementsPerByte = sizeof(ushort) / sizeof(byte);
+ length = ((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) / elementsPerByte;
+ }
+
+ SequentialScan:
+ while (length >= 4)
+ {
+ length -= 4;
+ pCh -= 4;
+
+ if (*(pCh + 3) == value)
+ goto Found3;
+ if (*(pCh + 2) == value)
+ goto Found2;
+ if (*(pCh + 1) == value)
+ goto Found1;
+ if (*pCh == value)
+ goto Found;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+ pCh -= 1;
+
+ if (*pCh == value)
+ goto Found;
+ }
+
+ // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow
+ // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
+ if (Vector.IsHardwareAccelerated && pCh > pEndCh)
+ {
+ // Get the highest multiple of Vector<ushort>.Count that is within the search space.
+ // That will be how many times we iterate in the loop below.
+ // This is equivalent to: length = Vector<ushort>.Count * ((int)(pCh - pEndCh) / Vector<ushort>.Count)
+ length = (int)((pCh - pEndCh) & ~(Vector<ushort>.Count - 1));
+
+ // Get comparison Vector
+ Vector<ushort> vComparison = new Vector<ushort>(value);
+
+ while (length > 0)
+ {
+ char* pStart = pCh - Vector<ushort>.Count;
+ // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh (and hence pSart) is always vector aligned
+ Debug.Assert(((int)pStart & (Unsafe.SizeOf<Vector<ushort>>() - 1)) == 0);
+ Vector<ushort> vMatches = Vector.Equals(vComparison, Unsafe.Read<Vector<ushort>>(pStart));
+ if (Vector<ushort>.Zero.Equals(vMatches))
+ {
+ pCh -= Vector<ushort>.Count;
+ length -= Vector<ushort>.Count;
+ continue;
+ }
+ // Find offset of last match
+ return (int)(pStart - pEndCh) + LocateLastFoundChar(vMatches);
+ }
+
+ if (pCh > pEndCh)
+ {
+ length = (int)(pCh - pEndCh);
+ goto SequentialScan;
+ }
+ }
+
+ return -1;
+ Found:
+ return (int)(pCh - pEndCh);
+ Found1:
+ return (int)(pCh - pEndCh) + 1;
+ Found2:
+ return (int)(pCh - pEndCh) + 2;
+ Found3:
+ return (int)(pCh - pEndCh) + 3;
+ }
+ }
+
+ // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateFirstFoundChar(Vector<ushort> match)
+ {
+ var vector64 = Vector.AsVectorUInt64(match);
+ ulong candidate = 0;
+ int i = 0;
+ // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
+ for (; i < Vector<ulong>.Count; i++)
+ {
+ candidate = vector64[i];
+ if (candidate != 0)
+ {
+ break;
+ }
+ }
+
+ // Single LEA instruction with jitted const (using function result)
+ return i * 4 + LocateFirstFoundChar(candidate);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateFirstFoundChar(ulong match)
+ {
+ unchecked
+ {
+ // Flag least significant power of two bit
+ var powerOfTwoFlag = match ^ (match - 1);
+ // Shift all powers of two into the high byte and extract
+ return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49);
+ }
+ }
+
+ private const ulong XorPowerOfTwoToHighChar = (0x03ul |
+ 0x02ul << 16 |
+ 0x01ul << 32) + 1;
+
+ // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateLastFoundChar(Vector<ushort> match)
+ {
+ var vector64 = Vector.AsVectorUInt64(match);
+ ulong candidate = 0;
+ int i = Vector<ulong>.Count - 1;
+ // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
+ for (; i >= 0; i--)
+ {
+ candidate = vector64[i];
+ if (candidate != 0)
+ {
+ break;
+ }
+ }
+
+ // Single LEA instruction with jitted const (using function result)
+ return i * 4 + LocateLastFoundChar(candidate);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateLastFoundChar(ulong match)
+ {
+ // Find the most significant char that has its highest bit set
+ int index = 3;
+ while ((long)match > 0)
+ {
+ match = match << 16;
+ index--;
+ }
+ return index;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs
index d1c62c8d5..d6f45d226 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs
@@ -3,16 +3,16 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices; // Do not remove. This is necessary for netstandard, since this file is mirrored into corefx
+using System.Numerics;
#if !netstandard
using Internal.Runtime.CompilerServices;
-#else
-using System.Runtime.CompilerServices;
#endif
namespace System
{
- internal static partial class SpanHelpers
+ internal static partial class SpanHelpers // .T
{
public static int IndexOf<T>(ref T searchSpace, int searchSpaceLength, ref T value, int valueLength)
where T : IEquatable<T>
@@ -49,7 +49,64 @@ namespace System
}
return -1;
}
-
+
+ // Adapted from IndexOf(...)
+ public static bool Contains<T>(ref T searchSpace, T value, int length)
+ where T : IEquatable<T>
+ {
+ Debug.Assert(length >= 0);
+
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ while (length >= 8)
+ {
+ length -= 8;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, index + 0)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 1)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 2)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 3)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 4)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 5)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 6)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 7)))
+ {
+ goto Found;
+ }
+
+ index += 8;
+ }
+
+ if (length >= 4)
+ {
+ length -= 4;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, index + 0)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 1)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 2)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 3)))
+ {
+ goto Found;
+ }
+
+ index += 4;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, index)))
+ goto Found;
+
+ index += 1;
+ }
+
+ return false;
+
+ Found:
+ return true;
+ }
+
public static unsafe int IndexOf<T>(ref T searchSpace, T value, int length)
where T : IEquatable<T>
{
@@ -189,21 +246,21 @@ namespace System
}
return -1;
- Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
+ Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return index;
- Found1:
+ Found1:
return index + 1;
- Found2:
+ Found2:
return index + 2;
- Found3:
+ Found3:
return index + 3;
- Found4:
+ Found4:
return index + 4;
- Found5:
+ Found5:
return index + 5;
- Found6:
+ Found6:
return index + 6;
- Found7:
+ Found7:
return index + 7;
}
@@ -272,21 +329,21 @@ namespace System
}
return -1;
- Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
+ Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return index;
- Found1:
+ Found1:
return index + 1;
- Found2:
+ Found2:
return index + 2;
- Found3:
+ Found3:
return index + 3;
- Found4:
+ Found4:
return index + 4;
- Found5:
+ Found5:
return index + 5;
- Found6:
+ Found6:
return index + 6;
- Found7:
+ Found7:
return index + 7;
}
@@ -309,7 +366,8 @@ namespace System
// Reduce space for search, cause we don't care if we find the search value after the index of a previously found value
searchSpaceLength = tempIndex;
- if (index == 0) break;
+ if (index == 0)
+ break;
}
}
return index;
@@ -595,7 +653,8 @@ namespace System
for (int i = 0; i < valueLength; i++)
{
var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
- if (tempIndex > index) index = tempIndex;
+ if (tempIndex > index)
+ index = tempIndex;
}
return index;
}
@@ -671,11 +730,13 @@ namespace System
Debug.Assert(secondLength >= 0);
var minLength = firstLength;
- if (minLength > secondLength) minLength = secondLength;
+ if (minLength > secondLength)
+ minLength = secondLength;
for (int i = 0; i < minLength; i++)
{
int result = Unsafe.Add(ref first, i).CompareTo(Unsafe.Add(ref second, i));
- if (result != 0) return result;
+ if (result != 0)
+ return result;
}
return firstLength.CompareTo(secondLength);
}
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.cs
index dad0f6294..0d5c57c5d 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.cs
@@ -5,7 +5,6 @@
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
-using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;
@@ -19,127 +18,6 @@ namespace System
{
internal static partial class SpanHelpers
{
- public static int IndexOfCultureHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(span.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return CompareInfo.InvariantIndexOf(span, value, ignoreCase: false);
- }
-
- return compareInfo.IndexOf(span, value, CompareOptions.None);
- }
-
- public static int IndexOfCultureIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(span.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return CompareInfo.InvariantIndexOf(span, value, ignoreCase: true);
- }
-
- return compareInfo.IndexOf(span, value, CompareOptions.IgnoreCase);
- }
-
- public static int IndexOfOrdinalHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, bool ignoreCase)
- {
- Debug.Assert(span.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return CompareInfo.InvariantIndexOf(span, value, ignoreCase);
- }
-
- return CompareInfo.Invariant.IndexOfOrdinal(span, value, ignoreCase);
- }
-
- public static bool StartsWithCultureHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return span.StartsWith(value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsPrefix(span, value, CompareOptions.None);
- }
-
- public static bool StartsWithCultureIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return StartsWithOrdinalIgnoreCaseHelper(span, value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsPrefix(span, value, CompareOptions.IgnoreCase);
- }
-
- public static bool StartsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value)
- {
- Debug.Assert(value.Length != 0);
-
- if (span.Length < value.Length)
- {
- return false;
- }
- return CompareInfo.CompareOrdinalIgnoreCase(span.Slice(0, value.Length), value) == 0;
- }
-
- public static bool EndsWithCultureHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return span.EndsWith(value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsSuffix(span, value, CompareOptions.None);
- }
-
- public static bool EndsWithCultureIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return EndsWithOrdinalIgnoreCaseHelper(span, value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsSuffix(span, value, CompareOptions.IgnoreCase);
- }
-
- public static bool EndsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value)
- {
- Debug.Assert(value.Length != 0);
-
- if (span.Length < value.Length)
- {
- return false;
- }
- return (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0);
- }
-
public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength)
{
if (byteLength == 0)
@@ -355,13 +233,13 @@ namespace System
nuint i = 0; // byte offset at which we're copying
- if ((Unsafe.As<byte, int>(ref b) & 3) != 0)
+ if (((nuint)Unsafe.AsPointer(ref b) & 3) != 0)
{
- if ((Unsafe.As<byte, int>(ref b) & 1) != 0)
+ if (((nuint)Unsafe.AsPointer(ref b) & 1) != 0)
{
- Unsafe.AddByteOffset<byte>(ref b, i) = 0;
+ b = 0;
i += 1;
- if ((Unsafe.As<byte, int>(ref b) & 2) != 0)
+ if (((nuint)Unsafe.AsPointer(ref b) & 2) != 0)
goto IntAligned;
}
Unsafe.As<byte, short>(ref Unsafe.AddByteOffset<byte>(ref b, i)) = 0;
@@ -378,7 +256,7 @@ namespace System
// The thing 1, 2, 3, and 4 have in common that the others don't is that if you
// subtract one from them, their 3rd lsb will not be set. Hence, the below check.
- if (((Unsafe.As<byte, int>(ref b) - 1) & 4) == 0)
+ if ((((nuint)Unsafe.AsPointer(ref b) - 1) & 4) == 0)
{
Unsafe.As<byte, int>(ref Unsafe.AddByteOffset<byte>(ref b, i)) = 0;
i += 4;
@@ -461,43 +339,77 @@ namespace System
public static unsafe void ClearWithReferences(ref IntPtr ip, nuint pointerSizeLength)
{
- if (pointerSizeLength == 0)
- return;
+ Debug.Assert((int)Unsafe.AsPointer(ref ip) % sizeof(IntPtr) == 0, "Should've been aligned on natural word boundary.");
- // TODO: Perhaps do switch casing to improve small size perf
+ // First write backward 8 natural words at a time.
+ // Writing backward allows us to get away with only simple modifications to the
+ // mov instruction's base and index registers between loop iterations.
- nuint i = 0;
- nuint n = 0;
- while ((n = i + 8) <= (pointerSizeLength))
+ for (; pointerSizeLength >= 8; pointerSizeLength -= 8)
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 1) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 2) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 3) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 4) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 5) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 6) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 7) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- i = n;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -1) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -2) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -3) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -4) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -5) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -6) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -7) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -8) = default;
}
- if ((n = i + 4) <= (pointerSizeLength))
+
+ Debug.Assert(pointerSizeLength <= 7);
+
+ // The logic below works by trying to minimize the number of branches taken for any
+ // given range of lengths. For example, the lengths [ 4 .. 7 ] are handled by a single
+ // branch, [ 2 .. 3 ] are handled by a single branch, and [ 1 ] is handled by a single
+ // branch.
+ //
+ // We can write both forward and backward as a perf improvement. For example,
+ // the lengths [ 4 .. 7 ] can be handled by zeroing out the first four natural
+ // words and the last 3 natural words. In the best case (length = 7), there are
+ // no overlapping writes. In the worst case (length = 4), there are three
+ // overlapping writes near the middle of the buffer. In perf testing, the
+ // penalty for performing duplicate writes is less expensive than the penalty
+ // for complex branching.
+
+ if (pointerSizeLength >= 4)
+ {
+ goto Write4To7;
+ }
+ else if (pointerSizeLength >= 2)
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 1) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 2) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 3) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- i = n;
+ goto Write2To3;
}
- if ((n = i + 2) <= (pointerSizeLength))
+ else if (pointerSizeLength > 0)
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 1) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- i = n;
+ goto Write1;
}
- if ((i + 1) <= (pointerSizeLength))
+ else
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
+ return; // nothing to write
}
+
+ Write4To7:
+ Debug.Assert(pointerSizeLength >= 4);
+
+ // Write first four and last three.
+ Unsafe.Add(ref ip, 2) = default;
+ Unsafe.Add(ref ip, 3) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -3) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -2) = default;
+
+ Write2To3:
+ Debug.Assert(pointerSizeLength >= 2);
+
+ // Write first two and last one.
+ Unsafe.Add(ref ip, 1) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -1) = default;
+
+ Write1:
+ Debug.Assert(pointerSizeLength >= 1);
+
+ // Write only element.
+ ip = default;
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/StackOverflowException.cs b/src/System.Private.CoreLib/shared/System/StackOverflowException.cs
index 6f954cc75..a603ea88b 100644
--- a/src/System.Private.CoreLib/shared/System/StackOverflowException.cs
+++ b/src/System.Private.CoreLib/shared/System/StackOverflowException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_STACKOVERFLOW;
}
- public StackOverflowException(String message)
+ public StackOverflowException(string message)
: base(message)
{
HResult = HResults.COR_E_STACKOVERFLOW;
}
- public StackOverflowException(String message, Exception innerException)
+ public StackOverflowException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_STACKOVERFLOW;
diff --git a/src/System.Private.CoreLib/shared/System/String.Comparison.cs b/src/System.Private.CoreLib/shared/System/String.Comparison.cs
new file mode 100644
index 000000000..267bfe1fd
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/String.Comparison.cs
@@ -0,0 +1,905 @@
+// 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.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+using Internal.Runtime.CompilerServices;
+
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif
+
+namespace System
+{
+ public partial class String
+ {
+ //
+ // Search/Query methods
+ //
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool EqualsHelper(string strA, string strB)
+ {
+ Debug.Assert(strA != null);
+ Debug.Assert(strB != null);
+ Debug.Assert(strA.Length == strB.Length);
+
+ return SpanHelpers.SequenceEqual(
+ ref Unsafe.As<char, byte>(ref strA.GetRawStringData()),
+ ref Unsafe.As<char, byte>(ref strB.GetRawStringData()),
+ ((nuint)strA.Length) * 2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int CompareOrdinalHelper(string strA, int indexA, int countA, string strB, int indexB, int countB)
+ {
+ Debug.Assert(strA != null);
+ Debug.Assert(strB != null);
+ Debug.Assert(indexA >= 0 && indexB >= 0);
+ Debug.Assert(countA >= 0 && countB >= 0);
+ Debug.Assert(indexA + countA <= strA.Length && indexB + countB <= strB.Length);
+
+ return SpanHelpers.SequenceCompareTo(ref Unsafe.Add(ref strA.GetRawStringData(), indexA), countA, ref Unsafe.Add(ref strB.GetRawStringData(), indexB), countB);
+ }
+
+ private static bool EqualsOrdinalIgnoreCase(string strA, string strB)
+ {
+ Debug.Assert(strA.Length == strB.Length);
+
+ return CompareInfo.EqualsOrdinalIgnoreCase(ref strA.GetRawStringData(), ref strB.GetRawStringData(), strB.Length);
+ }
+ private static unsafe int CompareOrdinalHelper(string strA, string strB)
+ {
+ Debug.Assert(strA != null);
+ Debug.Assert(strB != null);
+
+ // NOTE: This may be subject to change if eliminating the check
+ // in the callers makes them small enough to be inlined
+ Debug.Assert(strA._firstChar == strB._firstChar,
+ "For performance reasons, callers of this method should " +
+ "check/short-circuit beforehand if the first char is the same.");
+
+ int length = Math.Min(strA.Length, strB.Length);
+
+ fixed (char* ap = &strA._firstChar) fixed (char* bp = &strB._firstChar)
+ {
+ char* a = ap;
+ char* b = bp;
+
+ // Check if the second chars are different here
+ // The reason we check if _firstChar is different is because
+ // it's the most common case and allows us to avoid a method call
+ // to here.
+ // The reason we check if the second char is different is because
+ // if the first two chars the same we can increment by 4 bytes,
+ // leaving us word-aligned on both 32-bit (12 bytes into the string)
+ // and 64-bit (16 bytes) platforms.
+
+ // For empty strings, the second char will be null due to padding.
+ // The start of the string is the type pointer + string length, which
+ // takes up 8 bytes on 32-bit, 12 on x64. For empty strings the null
+ // terminator immediately follows, leaving us with an object
+ // 10/14 bytes in size. Since everything needs to be a multiple
+ // of 4/8, this will get padded and zeroed out.
+
+ // For one-char strings the second char will be the null terminator.
+
+ // NOTE: If in the future there is a way to read the second char
+ // without pinning the string (e.g. System.Runtime.CompilerServices.Unsafe
+ // is exposed to mscorlib, or a future version of C# allows inline IL),
+ // then do that and short-circuit before the fixed.
+
+ if (*(a + 1) != *(b + 1)) goto DiffOffset1;
+
+ // Since we know that the first two chars are the same,
+ // we can increment by 2 here and skip 4 bytes.
+ // This leaves us 8-byte aligned, which results
+ // on better perf for 64-bit platforms.
+ length -= 2; a += 2; b += 2;
+
+ // unroll the loop
+#if BIT64
+ while (length >= 12)
+ {
+ if (*(long*)a != *(long*)b) goto DiffOffset0;
+ if (*(long*)(a + 4) != *(long*)(b + 4)) goto DiffOffset4;
+ if (*(long*)(a + 8) != *(long*)(b + 8)) goto DiffOffset8;
+ length -= 12; a += 12; b += 12;
+ }
+#else // BIT64
+ while (length >= 10)
+ {
+ if (*(int*)a != *(int*)b) goto DiffOffset0;
+ if (*(int*)(a + 2) != *(int*)(b + 2)) goto DiffOffset2;
+ if (*(int*)(a + 4) != *(int*)(b + 4)) goto DiffOffset4;
+ if (*(int*)(a + 6) != *(int*)(b + 6)) goto DiffOffset6;
+ if (*(int*)(a + 8) != *(int*)(b + 8)) goto DiffOffset8;
+ length -= 10; a += 10; b += 10;
+ }
+#endif // BIT64
+
+ // Fallback loop:
+ // go back to slower code path and do comparison on 4 bytes at a time.
+ // This depends on the fact that the String objects are
+ // always zero terminated and that the terminating zero is not included
+ // in the length. For odd string sizes, the last compare will include
+ // the zero terminator.
+ while (length > 0)
+ {
+ if (*(int*)a != *(int*)b) goto DiffNextInt;
+ length -= 2;
+ a += 2;
+ b += 2;
+ }
+
+ // At this point, we have compared all the characters in at least one string.
+ // The longer string will be larger.
+ return strA.Length - strB.Length;
+
+#if BIT64
+ DiffOffset8: a += 4; b += 4;
+ DiffOffset4: a += 4; b += 4;
+#else // BIT64
+ // Use jumps instead of falling through, since
+ // otherwise going to DiffOffset8 will involve
+ // 8 add instructions before getting to DiffNextInt
+ DiffOffset8: a += 8; b += 8; goto DiffOffset0;
+ DiffOffset6: a += 6; b += 6; goto DiffOffset0;
+ DiffOffset4: a += 2; b += 2;
+ DiffOffset2: a += 2; b += 2;
+#endif // BIT64
+
+ DiffOffset0:
+ // If we reached here, we already see a difference in the unrolled loop above
+#if BIT64
+ if (*(int*)a == *(int*)b)
+ {
+ a += 2; b += 2;
+ }
+#endif // BIT64
+
+ DiffNextInt:
+ if (*a != *b) return *a - *b;
+
+ DiffOffset1:
+ Debug.Assert(*(a + 1) != *(b + 1), "This char must be different if we reach here!");
+ return *(a + 1) - *(b + 1);
+ }
+ }
+
+ // Provides a culture-correct string comparison. StrA is compared to StrB
+ // to determine whether it is lexicographically less, equal, or greater, and then returns
+ // either a negative integer, 0, or a positive integer; respectively.
+ //
+ public static int Compare(string strA, string strB)
+ {
+ return Compare(strA, strB, StringComparison.CurrentCulture);
+ }
+
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ // The case-sensitive option is set by ignoreCase
+ //
+ public static int Compare(string strA, string strB, bool ignoreCase)
+ {
+ var comparisonType = ignoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture;
+ return Compare(strA, strB, comparisonType);
+ }
+
+
+ // Provides a more flexible function for string comparison. See StringComparison
+ // for meaning of different comparisonType.
+ public static int Compare(string strA, string strB, StringComparison comparisonType)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ {
+ CheckStringComparison(comparisonType);
+ return 0;
+ }
+
+ // They can't both be null at this point.
+ if (strA == null)
+ {
+ CheckStringComparison(comparisonType);
+ return -1;
+ }
+ if (strB == null)
+ {
+ CheckStringComparison(comparisonType);
+ return 1;
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.Ordinal:
+ // Most common case: first character is different.
+ // Returns false for empty strings.
+ if (strA._firstChar != strB._firstChar)
+ {
+ return strA._firstChar - strB._firstChar;
+ }
+
+ return CompareOrdinalHelper(strA, strB);
+
+ case StringComparison.OrdinalIgnoreCase:
+ return CompareInfo.CompareOrdinalIgnoreCase(strA, strB);
+
+ default:
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
+ }
+
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ //
+ public static int Compare(string strA, string strB, CultureInfo culture, CompareOptions options)
+ {
+ if (culture == null)
+ {
+ throw new ArgumentNullException(nameof(culture));
+ }
+
+ return culture.CompareInfo.Compare(strA, strB, options);
+ }
+
+
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ // The case-sensitive option is set by ignoreCase, and the culture is set
+ // by culture
+ //
+ public static int Compare(string strA, string strB, bool ignoreCase, CultureInfo culture)
+ {
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ return Compare(strA, strB, culture, options);
+ }
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of given length is compared with the substring of strB
+ // beginning at indexB of the same length.
+ //
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length)
+ {
+ // NOTE: It's important we call the boolean overload, and not the StringComparison
+ // one. The two have some subtly different behavior (see notes in the former).
+ return Compare(strA, indexA, strB, indexB, length, ignoreCase: false);
+ }
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of given length is compared with the substring of strB
+ // beginning at indexB of the same length. Case sensitivity is determined by the ignoreCase boolean.
+ //
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase)
+ {
+ // Ideally we would just forward to the string.Compare overload that takes
+ // a StringComparison parameter, and just pass in CurrentCulture/CurrentCultureIgnoreCase.
+ // That function will return early if an optimization can be applied, e.g. if
+ // (object)strA == strB && indexA == indexB then it will return 0 straightaway.
+ // There are a couple of subtle behavior differences that prevent us from doing so
+ // however:
+ // - string.Compare(null, -1, null, -1, -1, StringComparison.CurrentCulture) works
+ // since that method also returns early for nulls before validation. It shouldn't
+ // for this overload.
+ // - Since we originally forwarded to CompareInfo.Compare for all of the argument
+ // validation logic, the ArgumentOutOfRangeExceptions thrown will contain different
+ // parameter names.
+ // Therefore, we have to duplicate some of the logic here.
+
+ int lengthA = length;
+ int lengthB = length;
+
+ if (strA != null)
+ {
+ lengthA = Math.Min(lengthA, strA.Length - indexA);
+ }
+
+ if (strB != null)
+ {
+ lengthB = Math.Min(lengthB, strB.Length - indexB);
+ }
+
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
+ }
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of length length is compared with the substring of strB
+ // beginning at indexB of the same length. Case sensitivity is determined by the ignoreCase boolean,
+ // and the culture is set by culture.
+ //
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase, CultureInfo culture)
+ {
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ return Compare(strA, indexA, strB, indexB, length, culture, options);
+ }
+
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of length length is compared with the substring of strB
+ // beginning at indexB of the same length.
+ //
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, CultureInfo culture, CompareOptions options)
+ {
+ if (culture == null)
+ {
+ throw new ArgumentNullException(nameof(culture));
+ }
+
+ int lengthA = length;
+ int lengthB = length;
+
+ if (strA != null)
+ {
+ lengthA = Math.Min(lengthA, strA.Length - indexA);
+ }
+
+ if (strB != null)
+ {
+ lengthB = Math.Min(lengthB, strB.Length - indexB);
+ }
+
+ return culture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
+ }
+
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, StringComparison comparisonType)
+ {
+ CheckStringComparison(comparisonType);
+
+ if (strA == null || strB == null)
+ {
+
+ if (object.ReferenceEquals(strA, strB))
+ {
+ // They're both null
+ return 0;
+ }
+
+ return strA == null ? -1 : 1;
+ }
+
+ if (length < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
+ }
+
+ if (indexA < 0 || indexB < 0)
+ {
+ string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB);
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
+ }
+
+ if (strA.Length - indexA < 0 || strB.Length - indexB < 0)
+ {
+ string paramName = strA.Length - indexA < 0 ? nameof(indexA) : nameof(indexB);
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
+ }
+
+ if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
+ {
+ return 0;
+ }
+
+ int lengthA = Math.Min(length, strA.Length - indexA);
+ int lengthB = Math.Min(length, strB.Length - indexB);
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.Ordinal:
+ return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
+
+ default:
+ Debug.Assert(comparisonType == StringComparison.OrdinalIgnoreCase); // CheckStringComparison validated these earlier
+ return CompareInfo.CompareOrdinalIgnoreCase(strA, indexA, lengthA, strB, indexB, lengthB);
+ }
+ }
+
+ // Compares strA and strB using an ordinal (code-point) comparison.
+ //
+ public static int CompareOrdinal(string strA, string strB)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ {
+ return 0;
+ }
+
+ // They can't both be null at this point.
+ if (strA == null)
+ {
+ return -1;
+ }
+ if (strB == null)
+ {
+ return 1;
+ }
+
+ // Most common case, first character is different.
+ // This will return false for empty strings.
+ if (strA._firstChar != strB._firstChar)
+ {
+ return strA._firstChar - strB._firstChar;
+ }
+
+ return CompareOrdinalHelper(strA, strB);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static int CompareOrdinal(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
+ => SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(strA), strA.Length, ref MemoryMarshal.GetReference(strB), strB.Length);
+
+ // Compares strA and strB using an ordinal (code-point) comparison.
+ //
+ public static int CompareOrdinal(string strA, int indexA, string strB, int indexB, int length)
+ {
+ if (strA == null || strB == null)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ {
+ // They're both null
+ return 0;
+ }
+
+ return strA == null ? -1 : 1;
+ }
+
+ // COMPAT: Checking for nulls should become before the arguments are validated,
+ // but other optimizations which allow us to return early should come after.
+
+ if (length < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeCount);
+ }
+
+ if (indexA < 0 || indexB < 0)
+ {
+ string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB);
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
+ }
+
+ int lengthA = Math.Min(length, strA.Length - indexA);
+ int lengthB = Math.Min(length, strB.Length - indexB);
+
+ if (lengthA < 0 || lengthB < 0)
+ {
+ string paramName = lengthA < 0 ? nameof(indexA) : nameof(indexB);
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
+ }
+
+ if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
+ {
+ return 0;
+ }
+
+ return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
+ }
+
+ // Compares this String to another String (cast as object), returning an integer that
+ // indicates the relationship. This method returns a value less than 0 if this is less than value, 0
+ // if this is equal to value, or a value greater than 0 if this is greater than value.
+ //
+ public int CompareTo(object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+
+ string other = value as string;
+
+ if (other == null)
+ {
+ throw new ArgumentException(SR.Arg_MustBeString);
+ }
+
+ return CompareTo(other); // will call the string-based overload
+ }
+
+ // Determines the sorting relation of StrB to the current instance.
+ //
+ public int CompareTo(string strB)
+ {
+ return string.Compare(this, strB, StringComparison.CurrentCulture);
+ }
+
+ // Determines whether a specified string is a suffix of the current instance.
+ //
+ // The case-sensitive and culture-sensitive option is set by options,
+ // and the default culture is used.
+ //
+ public bool EndsWith(string value)
+ {
+ return EndsWith(value, StringComparison.CurrentCulture);
+ }
+
+ public bool EndsWith(string value, StringComparison comparisonType)
+ {
+ if ((object)value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ if ((object)this == (object)value)
+ {
+ CheckStringComparison(comparisonType);
+ return true;
+ }
+
+ if (value.Length == 0)
+ {
+ CheckStringComparison(comparisonType);
+ return true;
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.Ordinal:
+ return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
+
+ case StringComparison.OrdinalIgnoreCase:
+ return this.Length < value.Length ? false : (CompareInfo.CompareOrdinalIgnoreCase(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
+
+ default:
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
+ }
+
+ public bool EndsWith(string value, bool ignoreCase, CultureInfo culture)
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ if ((object)this == (object)value)
+ {
+ return true;
+ }
+
+ CultureInfo referenceCulture = culture ?? CultureInfo.CurrentCulture;
+ return referenceCulture.CompareInfo.IsSuffix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+
+ public bool EndsWith(char value)
+ {
+ int thisLen = Length;
+ return thisLen != 0 && this[thisLen - 1] == value;
+ }
+
+ // Determines whether two strings match.
+ public override bool Equals(object obj)
+ {
+ if (object.ReferenceEquals(this, obj))
+ return true;
+
+ string str = obj as string;
+ if (str == null)
+ return false;
+
+ if (this.Length != str.Length)
+ return false;
+
+ return EqualsHelper(this, str);
+ }
+
+ // Determines whether two strings match.
+ public bool Equals(string value)
+ {
+ if (object.ReferenceEquals(this, value))
+ return true;
+
+ // NOTE: No need to worry about casting to object here.
+ // If either side of an == comparison between strings
+ // is null, Roslyn generates a simple ceq instruction
+ // instead of calling string.op_Equality.
+ if (value == null)
+ return false;
+
+ if (this.Length != value.Length)
+ return false;
+
+ return EqualsHelper(this, value);
+ }
+
+ public bool Equals(string value, StringComparison comparisonType)
+ {
+ if ((object)this == (object)value)
+ {
+ CheckStringComparison(comparisonType);
+ return true;
+ }
+
+ if ((object)value == null)
+ {
+ CheckStringComparison(comparisonType);
+ return false;
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return (CompareInfo.Invariant.Compare(this, value, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
+
+ case StringComparison.Ordinal:
+ if (this.Length != value.Length)
+ return false;
+ return EqualsHelper(this, value);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (this.Length != value.Length)
+ return false;
+
+ return EqualsOrdinalIgnoreCase(this, value);
+
+ default:
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
+ }
+
+
+ // Determines whether two Strings match.
+ public static bool Equals(string a, string b)
+ {
+ if ((object)a == (object)b)
+ {
+ return true;
+ }
+
+ if ((object)a == null || (object)b == null || a.Length != b.Length)
+ {
+ return false;
+ }
+
+ return EqualsHelper(a, b);
+ }
+
+ public static bool Equals(string a, string b, StringComparison comparisonType)
+ {
+ if ((object)a == (object)b)
+ {
+ CheckStringComparison(comparisonType);
+ return true;
+ }
+
+ if ((object)a == null || (object)b == null)
+ {
+ CheckStringComparison(comparisonType);
+ return false;
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return (CompareInfo.Invariant.Compare(a, b, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
+
+ case StringComparison.Ordinal:
+ if (a.Length != b.Length)
+ return false;
+ return EqualsHelper(a, b);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (a.Length != b.Length)
+ return false;
+
+ return EqualsOrdinalIgnoreCase(a, b);
+
+ default:
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
+ }
+
+ public static bool operator ==(string a, string b)
+ {
+ return string.Equals(a, b);
+ }
+
+ public static bool operator !=(string a, string b)
+ {
+ return !string.Equals(a, b);
+ }
+
+ // Gets a hash code for this string. If strings A and B are such that A.Equals(B), then
+ // they will return the same hash code.
+ public override int GetHashCode()
+ {
+#if MONO
+ return LegacyStringGetHashCode();
+#else
+ return Marvin.ComputeHash32(ref Unsafe.As<char, byte>(ref _firstChar), _stringLength * 2, Marvin.DefaultSeed);
+#endif
+ }
+
+ // Gets a hash code for this string and this comparison. If strings A and B and comparison C are such
+ // that string.Equals(A, B, C), then they will return the same hash code with this comparison C.
+ public int GetHashCode(StringComparison comparisonType) => StringComparer.FromComparison(comparisonType).GetHashCode(this);
+
+ // Use this if and only if 'Denial of Service' attacks are not a concern (i.e. never used for free-form user input),
+ // or are otherwise mitigated
+ internal unsafe int GetNonRandomizedHashCode()
+ {
+ fixed (char* src = &_firstChar)
+ {
+ Debug.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'");
+ Debug.Assert(((int)src) % 4 == 0, "Managed string should start at 4 bytes boundary");
+
+ uint hash1 = (5381 << 16) + 5381;
+ uint hash2 = hash1;
+
+ uint* ptr = (uint*)src;
+ int length = this.Length;
+
+ while (length > 2)
+ {
+ length -= 4;
+ // Where length is 4n-1 (e.g. 3,7,11,15,19) this additionally consumes the null terminator
+ hash1 = (((hash1 << 5) | (hash1 >> 27)) + hash1) ^ ptr[0];
+ hash2 = (((hash2 << 5) | (hash2 >> 27)) + hash2) ^ ptr[1];
+ ptr += 2;
+ }
+
+ if (length > 0)
+ {
+ // Where length is 4n-3 (e.g. 1,5,9,13,17) this additionally consumes the null terminator
+ hash2 = (((hash2 << 5) | (hash2 >> 27)) + hash2) ^ ptr[0];
+ }
+
+ return (int)(hash1 + (hash2 * 1566083941));
+ }
+ }
+
+ // Determines whether a specified string is a prefix of the current instance
+ //
+ public bool StartsWith(string value)
+ {
+ if ((object)value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ return StartsWith(value, StringComparison.CurrentCulture);
+ }
+
+ public bool StartsWith(string value, StringComparison comparisonType)
+ {
+ if ((object)value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ if ((object)this == (object)value)
+ {
+ CheckStringComparison(comparisonType);
+ return true;
+ }
+
+ if (value.Length == 0)
+ {
+ CheckStringComparison(comparisonType);
+ return true;
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.IsPrefix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.Ordinal:
+ if (this.Length < value.Length || _firstChar != value._firstChar)
+ {
+ return false;
+ }
+ return (value.Length == 1) ?
+ true : // First char is the same and thats all there is to compare
+ SpanHelpers.SequenceEqual(
+ ref Unsafe.As<char, byte>(ref this.GetRawStringData()),
+ ref Unsafe.As<char, byte>(ref value.GetRawStringData()),
+ ((nuint)value.Length) * 2);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (this.Length < value.Length)
+ {
+ return false;
+ }
+ return CompareInfo.EqualsOrdinalIgnoreCase(ref this.GetRawStringData(), ref value.GetRawStringData(), value.Length);
+
+ default:
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
+ }
+
+ public bool StartsWith(string value, bool ignoreCase, CultureInfo culture)
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ if ((object)this == (object)value)
+ {
+ return true;
+ }
+
+ CultureInfo referenceCulture = culture ?? CultureInfo.CurrentCulture;
+ return referenceCulture.CompareInfo.IsPrefix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+
+ public bool StartsWith(char value) => Length != 0 && _firstChar == value;
+
+ internal static void CheckStringComparison(StringComparison comparisonType)
+ {
+ // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
+ if ((uint)comparisonType > (uint)StringComparison.OrdinalIgnoreCase)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.NotSupported_StringComparison, ExceptionArgument.comparisonType);
+ }
+ }
+
+ internal static CompareOptions GetCaseCompareOfComparisonCulture(StringComparison comparisonType)
+ {
+ Debug.Assert((uint)comparisonType <= (uint)StringComparison.OrdinalIgnoreCase);
+
+ // Culture enums can be & with CompareOptions.IgnoreCase 0x01 to extract if IgnoreCase or CompareOptions.None 0x00
+ //
+ // CompareOptions.None 0x00
+ // CompareOptions.IgnoreCase 0x01
+ //
+ // StringComparison.CurrentCulture: 0x00
+ // StringComparison.InvariantCulture: 0x02
+ // StringComparison.Ordinal 0x04
+ //
+ // StringComparison.CurrentCultureIgnoreCase: 0x01
+ // StringComparison.InvariantCultureIgnoreCase: 0x03
+ // StringComparison.OrdinalIgnoreCase 0x05
+
+ return (CompareOptions)((int)comparisonType & (int)CompareOptions.IgnoreCase);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/String.Manipulation.cs b/src/System.Private.CoreLib/shared/System/String.Manipulation.cs
index 9ea2ef0f0..3da96bb3b 100644
--- a/src/System.Private.CoreLib/shared/System/String.Manipulation.cs
+++ b/src/System.Private.CoreLib/shared/System/String.Manipulation.cs
@@ -897,7 +897,7 @@ namespace System
return result;
}
- // a remove that just takes a startindex.
+ // a remove that just takes a startindex.
public string Remove(int startIndex)
{
if (startIndex < 0)
@@ -919,16 +919,12 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase);
+ return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);
+ return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
return Replace(oldValue, newValue);
@@ -1140,7 +1136,7 @@ namespace System
int count = replacementIdx - thisIdx;
if (count != 0)
{
- this.AsSpan().Slice(thisIdx, count).CopyTo(dstSpan.Slice(dstIdx));
+ this.AsSpan(thisIdx, count).CopyTo(dstSpan.Slice(dstIdx));
dstIdx += count;
}
thisIdx = replacementIdx + oldValueLength;
@@ -1152,7 +1148,7 @@ namespace System
// Copy over the final non-matching portion at the end of the string.
Debug.Assert(this.Length - thisIdx == dstSpan.Length - dstIdx);
- this.AsSpan().Slice(thisIdx).CopyTo(dstSpan.Slice(dstIdx));
+ this.AsSpan(thisIdx).CopyTo(dstSpan.Slice(dstIdx));
return dst;
}
@@ -1252,7 +1248,7 @@ namespace System
return new string[] { this };
}
- string[] result = omitEmptyEntries
+ string[] result = omitEmptyEntries
? SplitOmitEmptyEntries(sepList, default, 1, count)
: SplitKeepEmptyEntries(sepList, default, 1, count);
@@ -1266,7 +1262,7 @@ namespace System
return SplitInternal(separator ?? string.Empty, null, int.MaxValue, options);
}
- public string[] Split(string separator, Int32 count, StringSplitOptions options = StringSplitOptions.None)
+ public string[] Split(string separator, int count, StringSplitOptions options = StringSplitOptions.None)
{
return SplitInternal(separator ?? string.Empty, null, count, options);
}
@@ -1276,7 +1272,7 @@ namespace System
return SplitInternal(null, separator, int.MaxValue, options);
}
- public string[] Split(string[] separator, Int32 count, StringSplitOptions options)
+ public string[] Split(string[] separator, int count, StringSplitOptions options)
{
return SplitInternal(null, separator, count, options);
}
@@ -1317,7 +1313,7 @@ namespace System
{
return SplitInternal(separator, count, options);
}
-
+
Span<int> sepListInitialSpan = stackalloc int[StackallocIntBufferSizeLimit];
var sepListBuilder = new ValueListBuilder<int>(sepListInitialSpan);
@@ -1327,14 +1323,14 @@ namespace System
MakeSeparatorList(separators, ref sepListBuilder, ref lengthListBuilder);
ReadOnlySpan<int> sepList = sepListBuilder.AsSpan();
ReadOnlySpan<int> lengthList = lengthListBuilder.AsSpan();
-
+
// Handle the special case of no replaces.
if (sepList.Length == 0)
{
return new string[] { this };
}
- string[] result = omitEmptyEntries
+ string[] result = omitEmptyEntries
? SplitOmitEmptyEntries(sepList, lengthList, 0, count)
: SplitKeepEmptyEntries(sepList, lengthList, 0, count);
@@ -1357,7 +1353,7 @@ namespace System
return new string[] { this };
}
- string[] result = options == StringSplitOptions.RemoveEmptyEntries
+ string[] result = options == StringSplitOptions.RemoveEmptyEntries
? SplitOmitEmptyEntries(sepList, default, separator.Length, count)
: SplitKeepEmptyEntries(sepList, default, separator.Length, count);
@@ -1402,15 +1398,15 @@ namespace System
}
- // This function will not keep the Empty string
+ // This function will not keep the Empty string
private string[] SplitOmitEmptyEntries(ReadOnlySpan<int> sepList, ReadOnlySpan<int> lengthList, int defaultLength, int count)
{
Debug.Assert(count >= 2);
int numReplaces = sepList.Length;
- // Allocate array to hold items. This array may not be
- // filled completely in this function, we will create a
+ // Allocate array to hold items. This array may not be
+ // filled completely in this function, we will create a
// new array and copy string references to that new array.
int maxItems = (numReplaces < count) ? (numReplaces + 1) : count;
string[] splitStrings = new string[maxItems];
@@ -1557,7 +1553,7 @@ namespace System
if (this[i] == separator[0] && currentSepLength <= Length - i)
{
if (currentSepLength == 1
- || CompareOrdinal(this, i, separator, 0, currentSepLength) == 0)
+ || this.AsSpan(i, currentSepLength).SequenceEqual(separator))
{
sepListBuilder.Append(i);
i += currentSepLength - 1;
@@ -1571,7 +1567,7 @@ namespace System
/// </summary>
/// <param name="separators">separator strngs</param>
/// <param name="sepListBuilder"><see cref="ValueListBuilder{T}"/> for separator indexes</param>
- /// <param name="lengthListBuilder"><see cref="ValueListBuilder{T}"/> for separator length values</param>
+ /// <param name="lengthListBuilder"><see cref="ValueListBuilder{T}"/> for separator length values</param>
private void MakeSeparatorList(string[] separators, ref ValueListBuilder<int> sepListBuilder, ref ValueListBuilder<int> lengthListBuilder)
{
Debug.Assert(separators != null && separators.Length > 0, "separators != null && separators.Length > 0");
@@ -1591,7 +1587,7 @@ namespace System
if (this[i] == separator[0] && currentSepLength <= Length - i)
{
if (currentSepLength == 1
- || CompareOrdinal(this, i, separator, 0, currentSepLength) == 0)
+ || this.AsSpan(i, currentSepLength).SequenceEqual(separator))
{
sepListBuilder.Append(i);
lengthListBuilder.Append(currentSepLength);
@@ -1702,7 +1698,7 @@ namespace System
}
// Trims the whitespace from both ends of the string. Whitespace is defined by
- // Char.IsWhiteSpace.
+ // char.IsWhiteSpace.
//
public string Trim() => TrimWhiteSpaceHelper(TrimType.Both);
diff --git a/src/System.Private.CoreLib/shared/System/String.Searching.cs b/src/System.Private.CoreLib/shared/System/String.Searching.cs
index c86d13524..7660c5225 100644
--- a/src/System.Private.CoreLib/shared/System/String.Searching.cs
+++ b/src/System.Private.CoreLib/shared/System/String.Searching.cs
@@ -22,10 +22,7 @@ namespace System
return (IndexOf(value, comparisonType) >= 0);
}
- public bool Contains(char value)
- {
- return IndexOf(value) != -1;
- }
+ public bool Contains(char value) => SpanHelpers.Contains(ref _firstChar, value, Length);
public bool Contains(char value, StringComparison comparisonType)
{
@@ -35,10 +32,7 @@ namespace System
// Returns the index of the first occurrence of a specified character in the current instance.
// The search starts at startIndex and runs thorough the next count characters.
//
- public int IndexOf(char value)
- {
- return IndexOf(value, 0, this.Length);
- }
+ public int IndexOf(char value) => SpanHelpers.IndexOf(ref _firstChar, value, Length);
public int IndexOf(char value, int startIndex)
{
@@ -50,19 +44,15 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.IndexOf(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
- return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.Ordinal);
+ return IndexOf(value);
case StringComparison.OrdinalIgnoreCase:
return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.OrdinalIgnoreCase);
@@ -80,116 +70,11 @@ namespace System
if ((uint)count > (uint)(Length - startIndex))
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- fixed (char* pChars = &_firstChar)
- {
- char* pCh = pChars + startIndex;
- char* pEndCh = pCh + count;
-
- if (Vector.IsHardwareAccelerated && count >= Vector<ushort>.Count * 2)
- {
- unchecked
- {
- const int elementsPerByte = sizeof(ushort) / sizeof(byte);
- int unaligned = ((int)pCh & (Vector<byte>.Count - 1)) / elementsPerByte;
- count = ((Vector<ushort>.Count - unaligned) & (Vector<ushort>.Count - 1));
- }
- }
- SequentialScan:
- while (count >= 4)
- {
- if (*pCh == value) goto ReturnIndex;
- if (*(pCh + 1) == value) goto ReturnIndex1;
- if (*(pCh + 2) == value) goto ReturnIndex2;
- if (*(pCh + 3) == value) goto ReturnIndex3;
-
- count -= 4;
- pCh += 4;
- }
-
- while (count > 0)
- {
- if (*pCh == value)
- goto ReturnIndex;
-
- count--;
- pCh++;
- }
-
- if (pCh < pEndCh)
- {
- count = (int)((pEndCh - pCh) & ~(Vector<ushort>.Count - 1));
- // Get comparison Vector
- Vector<ushort> vComparison = new Vector<ushort>(value);
- while (count > 0)
- {
- var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<ushort>>(pCh));
- if (Vector<ushort>.Zero.Equals(vMatches))
- {
- pCh += Vector<ushort>.Count;
- count -= Vector<ushort>.Count;
- continue;
- }
- // Find offset of first match
- return (int)(pCh - pChars) + LocateFirstFoundChar(vMatches);
- }
-
- if (pCh < pEndCh)
- {
- unchecked
- {
- count = (int)(pEndCh - pCh);
- }
- goto SequentialScan;
- }
- }
+ int result = SpanHelpers.IndexOf(ref Unsafe.Add(ref _firstChar, startIndex), value, count);
- return -1;
-
- ReturnIndex3: pCh++;
- ReturnIndex2: pCh++;
- ReturnIndex1: pCh++;
- ReturnIndex:
- return (int)(pCh - pChars);
- }
+ return result == -1 ? result : result + startIndex;
}
- // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateFirstFoundChar(Vector<ushort> match)
- {
- var vector64 = Vector.AsVectorUInt64(match);
- ulong candidate = 0;
- int i = 0;
- // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
- for (; i < Vector<ulong>.Count; i++)
- {
- candidate = vector64[i];
- if (candidate != 0)
- {
- break;
- }
- }
-
- // Single LEA instruction with jitted const (using function result)
- return i * 4 + LocateFirstFoundChar(candidate);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateFirstFoundChar(ulong match)
- {
- unchecked
- {
- // Flag least significant power of two bit
- var powerOfTwoFlag = match ^ (match - 1);
- // Shift all powers of two into the high byte and extract
- return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49);
- }
- }
-
- private const ulong XorPowerOfTwoToHighChar = (0x03ul |
- 0x02ul << 16 |
- 0x01ul << 32) + 1;
-
// Returns the index of the first occurrence of any specified character in the current instance.
// The search starts at startIndex and runs to startIndex + count - 1.
//
@@ -289,7 +174,7 @@ namespace System
private unsafe int IndexOfCharArray(char[] anyOf, int startIndex, int count)
{
// use probabilistic map, see InitializeProbabilisticMap
- ProbabilisticMap map = default(ProbabilisticMap);
+ ProbabilisticMap map = default;
uint* charMap = (uint*)&map;
InitializeProbabilisticMap(charMap, anyOf);
@@ -374,12 +259,12 @@ namespace System
return false;
}
- private unsafe static bool IsCharBitSet(uint* charMap, byte value)
+ private static unsafe bool IsCharBitSet(uint* charMap, byte value)
{
return (charMap[value & PROBABILISTICMAP_BLOCK_INDEX_MASK] & (1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT))) != 0;
}
- private unsafe static void SetCharBit(uint* charMap, byte value)
+ private static unsafe void SetCharBit(uint* charMap, byte value)
{
charMap[value & PROBABILISTICMAP_BLOCK_INDEX_MASK] |= 1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT);
}
@@ -434,22 +319,16 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
- return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: false);
-
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: true);
+ return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
@@ -461,10 +340,7 @@ namespace System
// The character at position startIndex is included in the search. startIndex is the larger
// index within the string.
//
- public int LastIndexOf(char value)
- {
- return LastIndexOf(value, this.Length - 1, this.Length);
- }
+ public int LastIndexOf(char value) => SpanHelpers.LastIndexOf(ref _firstChar, value, Length);
public int LastIndexOf(char value, int startIndex)
{
@@ -482,112 +358,10 @@ namespace System
if ((uint)count > (uint)startIndex + 1)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- fixed (char* pChars = &_firstChar)
- {
- char* pCh = pChars + startIndex;
- char* pEndCh = pCh - count;
-
- //We search [startIndex..EndIndex]
- if (Vector.IsHardwareAccelerated && count >= Vector<ushort>.Count * 2)
- {
- unchecked
- {
- const int elementsPerByte = sizeof(ushort) / sizeof(byte);
- count = (((int)pCh & (Vector<byte>.Count - 1)) / elementsPerByte) + 1;
- }
- }
- SequentialScan:
- while (count >= 4)
- {
- if (*pCh == value) goto ReturnIndex;
- if (*(pCh - 1) == value) goto ReturnIndex1;
- if (*(pCh - 2) == value) goto ReturnIndex2;
- if (*(pCh - 3) == value) goto ReturnIndex3;
+ int startSearchAt = startIndex + 1 - count;
+ int result = SpanHelpers.LastIndexOf(ref Unsafe.Add(ref _firstChar, startSearchAt), value, count);
- count -= 4;
- pCh -= 4;
- }
-
- while (count > 0)
- {
- if (*pCh == value)
- goto ReturnIndex;
-
- count--;
- pCh--;
- }
-
- if (pCh > pEndCh)
- {
- count = (int)((pCh - pEndCh) & ~(Vector<ushort>.Count - 1));
-
- // Get comparison Vector
- Vector<ushort> vComparison = new Vector<ushort>(value);
- while (count > 0)
- {
- char* pStart = pCh - Vector<ushort>.Count + 1;
- var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<ushort>>(pStart));
- if (Vector<ushort>.Zero.Equals(vMatches))
- {
- pCh -= Vector<ushort>.Count;
- count -= Vector<ushort>.Count;
- continue;
- }
- // Find offset of last match
- return (int)(pStart - pChars) + LocateLastFoundChar(vMatches);
- }
-
- if (pCh > pEndCh)
- {
- unchecked
- {
- count = (int)(pCh - pEndCh);
- }
- goto SequentialScan;
- }
- }
- return -1;
-
- ReturnIndex3: pCh--;
- ReturnIndex2: pCh--;
- ReturnIndex1: pCh--;
- ReturnIndex:
- return (int)(pCh - pChars);
- }
- }
-
- // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateLastFoundChar(Vector<ushort> match)
- {
- var vector64 = Vector.AsVectorUInt64(match);
- ulong candidate = 0;
- int i = Vector<ulong>.Count - 1;
- // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
- for (; i >= 0; i--)
- {
- candidate = vector64[i];
- if (candidate != 0)
- {
- break;
- }
- }
-
- // Single LEA instruction with jitted const (using function result)
- return i * 4 + LocateLastFoundChar(candidate);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateLastFoundChar(ulong match)
- {
- // Find the most significant char that has its highest bit set
- int index = 3;
- while ((long)match > 0)
- {
- match = match << 16;
- index--;
- }
- return index;
+ return result == -1 ? result : result + startSearchAt;
}
// Returns the index of the last occurrence of any specified character in the current instance.
@@ -640,7 +414,7 @@ namespace System
private unsafe int LastIndexOfCharArray(char[] anyOf, int startIndex, int count)
{
// use probabilistic map, see InitializeProbabilisticMap
- ProbabilisticMap map = default(ProbabilisticMap);
+ ProbabilisticMap map = default;
uint* charMap = (uint*)&map;
InitializeProbabilisticMap(charMap, anyOf);
@@ -735,22 +509,16 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
- return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: false);
-
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: true);
+ return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
diff --git a/src/System.Private.CoreLib/shared/System/String.cs b/src/System.Private.CoreLib/shared/System/String.cs
new file mode 100644
index 000000000..c573072eb
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/String.cs
@@ -0,0 +1,794 @@
+// 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.Buffers;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Text;
+
+namespace System
+{
+ // The String class represents a static string of characters. Many of
+ // the string methods perform some type of transformation on the current
+ // instance and return the result as a new string. As with arrays, character
+ // positions (indices) are zero-based.
+
+ [Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public sealed partial class String : IComparable, IEnumerable, IConvertible, IEnumerable<char>, IComparable<string>, IEquatable<string>, ICloneable
+ {
+ // String constructors
+ // These are special. The implementation methods for these have a different signature from the
+ // declared constructors.
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.Char[])")]
+ public extern String(char[] value);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private string Ctor(char[] value)
+ {
+ if (value == null || value.Length == 0)
+ return Empty;
+
+ string result = FastAllocateString(value.Length);
+ unsafe
+ {
+ fixed (char* dest = &result._firstChar, source = value)
+ wstrcpy(dest, source, value.Length);
+ }
+ return result;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.Char[], System.Int32, System.Int32)")]
+ public extern String(char[] value, int startIndex, int length);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private string Ctor(char[] value, int startIndex, int length)
+ {
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
+
+ if (startIndex > value.Length - length)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
+
+ if (length == 0)
+ return Empty;
+
+ string result = FastAllocateString(length);
+ unsafe
+ {
+ fixed (char* dest = &result._firstChar, source = value)
+ wstrcpy(dest, source + startIndex, length);
+ }
+ return result;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.Char*)")]
+ public extern unsafe String(char* value);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(char* ptr)
+ {
+ if (ptr == null)
+ return Empty;
+
+ int count = wcslen(ptr);
+ if (count == 0)
+ return Empty;
+
+ string result = FastAllocateString(count);
+ fixed (char* dest = &result._firstChar)
+ wstrcpy(dest, ptr, count);
+ return result;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.Char*, System.Int32, System.Int32)")]
+ public extern unsafe String(char* value, int startIndex, int length);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(char* ptr, int startIndex, int length)
+ {
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
+
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
+
+ char* pStart = ptr + startIndex;
+
+ // overflow check
+ if (pStart < ptr)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_PartialWCHAR);
+
+ if (length == 0)
+ return Empty;
+
+ if (ptr == null)
+ throw new ArgumentOutOfRangeException(nameof(ptr), SR.ArgumentOutOfRange_PartialWCHAR);
+
+ string result = FastAllocateString(length);
+ fixed (char* dest = &result._firstChar)
+ wstrcpy(dest, pStart, length);
+ return result;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.SByte*)")]
+ public extern unsafe String(sbyte* value);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(sbyte* value)
+ {
+ byte* pb = (byte*)value;
+ if (pb == null)
+ return Empty;
+
+ int numBytes = new ReadOnlySpan<byte>((byte*)value, int.MaxValue).IndexOf<byte>(0);
+
+ // Check for overflow
+ if (numBytes < 0)
+ throw new ArgumentException(SR.Arg_MustBeNullTerminatedString);
+
+ return CreateStringForSByteConstructor(pb, numBytes);
+ }
+
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.SByte*, System.Int32, System.Int32)")]
+ public extern unsafe String(sbyte* value, int startIndex, int length);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(sbyte* value, int startIndex, int length)
+ {
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
+
+ if (value == null)
+ {
+ if (length == 0)
+ return Empty;
+
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ byte* pStart = (byte*)(value + startIndex);
+
+ // overflow check
+ if (pStart < value)
+ throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_PartialWCHAR);
+
+ return CreateStringForSByteConstructor(pStart, length);
+ }
+
+ // Encoder for String..ctor(sbyte*) and String..ctor(sbyte*, int, int)
+ private static unsafe string CreateStringForSByteConstructor(byte *pb, int numBytes)
+ {
+ Debug.Assert(numBytes >= 0);
+ Debug.Assert(pb <= (pb + numBytes));
+
+ if (numBytes == 0)
+ return Empty;
+
+#if PLATFORM_WINDOWS
+ int numCharsRequired = Interop.Kernel32.MultiByteToWideChar(Interop.Kernel32.CP_ACP, Interop.Kernel32.MB_PRECOMPOSED, pb, numBytes, (char*)null, 0);
+ if (numCharsRequired == 0)
+ throw new ArgumentException(SR.Arg_InvalidANSIString);
+
+ string newString = FastAllocateString(numCharsRequired);
+ fixed (char *pFirstChar = &newString._firstChar)
+ {
+ numCharsRequired = Interop.Kernel32.MultiByteToWideChar(Interop.Kernel32.CP_ACP, Interop.Kernel32.MB_PRECOMPOSED, pb, numBytes, pFirstChar, numCharsRequired);
+ }
+ if (numCharsRequired == 0)
+ throw new ArgumentException(SR.Arg_InvalidANSIString);
+ return newString;
+#else
+ return Encoding.UTF8.GetString(pb, numBytes);
+#endif
+ }
+
+ [CLSCompliant(false)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.SByte*, System.Int32, System.Int32, System.Text.Encoding)")]
+ public extern unsafe String(sbyte* value, int startIndex, int length, Encoding enc);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(sbyte* value, int startIndex, int length, Encoding enc)
+ {
+ if (enc == null)
+ return new string(value, startIndex, length);
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
+
+ if (value == null)
+ {
+ if (length == 0)
+ return Empty;
+
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ byte* pStart = (byte*)(value + startIndex);
+ if (pStart < value)
+ {
+ if (length == 0)
+ return Empty;
+
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ byte* pStart = (byte*)(value + startIndex);
+
+ // overflow check
+ if (pStart < value)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_PartialWCHAR);
+
+ return enc.GetString(new ReadOnlySpan<byte>(pStart, length));
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.Char, System.Int32)")]
+ public extern String(char c, int count);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private string Ctor(char c, int count)
+ {
+ if (count <= 0)
+ {
+ if (count == 0)
+ return Empty;
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
+ }
+
+ string result = FastAllocateString(count);
+
+ if (c != '\0') // Fast path null char string
+ {
+ unsafe
+ {
+ fixed (char* dest = &result._firstChar)
+ {
+ uint cc = (uint)((c << 16) | c);
+ uint* dmem = (uint*)dest;
+ if (count >= 4)
+ {
+ count -= 4;
+ do
+ {
+ dmem[0] = cc;
+ dmem[1] = cc;
+ dmem += 2;
+ count -= 4;
+ } while (count >= 0);
+ }
+ if ((count & 2) != 0)
+ {
+ *dmem = cc;
+ dmem++;
+ }
+ if ((count & 1) != 0)
+ ((char*)dmem)[0] = c;
+ }
+ }
+ }
+ return result;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [PreserveDependency("System.String.CreateString(System.ReadOnlySpan`1<System.Char>)")]
+ public extern String(ReadOnlySpan<char> value);
+
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(ReadOnlySpan<char> value)
+ {
+ if (value.Length == 0)
+ return Empty;
+
+ string result = FastAllocateString(value.Length);
+ fixed (char* dest = &result._firstChar, src = &MemoryMarshal.GetReference(value))
+ wstrcpy(dest, src, value.Length);
+ return result;
+ }
+
+ public static string Create<TState>(int length, TState state, SpanAction<char, TState> action)
+ {
+ if (action == null)
+ throw new ArgumentNullException(nameof(action));
+
+ if (length <= 0)
+ {
+ if (length == 0)
+ return Empty;
+ throw new ArgumentOutOfRangeException(nameof(length));
+ }
+
+ string result = FastAllocateString(length);
+ action(new Span<char>(ref result.GetRawStringData(), length), state);
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator ReadOnlySpan<char>(string value) =>
+ value != null ? new ReadOnlySpan<char>(ref value.GetRawStringData(), value.Length) : default;
+
+ public object Clone()
+ {
+ return this;
+ }
+
+ public static unsafe string Copy(string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException(nameof(str));
+
+ string result = FastAllocateString(str.Length);
+ fixed (char* dest = &result._firstChar, src = &str._firstChar)
+ wstrcpy(dest, src, str.Length);
+ return result;
+ }
+
+ // Converts a substring of this string to an array of characters. Copies the
+ // characters of this string beginning at position sourceIndex and ending at
+ // sourceIndex + count - 1 to the character array buffer, beginning
+ // at destinationIndex.
+ //
+ public unsafe void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
+ {
+ if (destination == null)
+ throw new ArgumentNullException(nameof(destination));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
+ if (sourceIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_Index);
+ if (count > Length - sourceIndex)
+ throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_IndexCount);
+ if (destinationIndex > destination.Length - count || destinationIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_IndexCount);
+
+ fixed (char* src = &_firstChar, dest = destination)
+ wstrcpy(dest + destinationIndex, src + sourceIndex, count);
+ }
+
+ // Returns the entire string as an array of characters.
+ public unsafe char[] ToCharArray()
+ {
+ if (Length == 0)
+ return Array.Empty<char>();
+
+ char[] chars = new char[Length];
+ fixed (char* src = &_firstChar, dest = &chars[0])
+ wstrcpy(dest, src, Length);
+ return chars;
+ }
+
+ // Returns a substring of this string as an array of characters.
+ //
+ public unsafe char[] ToCharArray(int startIndex, int length)
+ {
+ // Range check everything.
+ if (startIndex < 0 || startIndex > Length || startIndex > Length - length)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
+
+ if (length <= 0)
+ {
+ if (length == 0)
+ return Array.Empty<char>();
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
+ }
+
+ char[] chars = new char[length];
+ fixed (char* src = &_firstChar, dest = &chars[0])
+ wstrcpy(dest, src + startIndex, length);
+ return chars;
+ }
+
+ [NonVersionable]
+ public static bool IsNullOrEmpty(string value)
+ {
+ // Using 0u >= (uint)value.Length rather than
+ // value.Length == 0 as it will elide the bounds check to
+ // the first char: value[0] if that is performed following the test
+ // for the same test cost.
+ // Ternary operator returning true/false prevents redundant asm generation:
+ // https://github.com/dotnet/coreclr/issues/914
+ return (value == null || 0u >= (uint)value.Length) ? true : false;
+ }
+
+ public static bool IsNullOrWhiteSpace(string value)
+ {
+ if (value == null) return true;
+
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (!char.IsWhiteSpace(value[i])) return false;
+ }
+
+ return true;
+ }
+
+ internal ref char GetRawStringData() => ref _firstChar;
+
+ // Helper for encodings so they can talk to our buffer directly
+ // stringLength must be the exact size we'll expect
+ internal static unsafe string CreateStringFromEncoding(
+ byte* bytes, int byteLength, Encoding encoding)
+ {
+ Debug.Assert(bytes != null);
+ Debug.Assert(byteLength >= 0);
+
+ // Get our string length
+ int stringLength = encoding.GetCharCount(bytes, byteLength, null);
+ Debug.Assert(stringLength >= 0, "stringLength >= 0");
+
+ // They gave us an empty string if they needed one
+ // 0 bytelength might be possible if there's something in an encoder
+ if (stringLength == 0)
+ return Empty;
+
+ string s = FastAllocateString(stringLength);
+ fixed (char* pTempChars = &s._firstChar)
+ {
+ int doubleCheck = encoding.GetChars(bytes, byteLength, pTempChars, stringLength, null);
+ Debug.Assert(stringLength == doubleCheck,
+ "Expected encoding.GetChars to return same length as encoding.GetCharCount");
+ }
+
+ return s;
+ }
+
+ // This is only intended to be used by char.ToString.
+ // It is necessary to put the code in this class instead of Char, since _firstChar is a private member.
+ // Making _firstChar internal would be dangerous since it would make it much easier to break String's immutability.
+ internal static string CreateFromChar(char c)
+ {
+ string result = FastAllocateString(1);
+ result._firstChar = c;
+ return result;
+ }
+
+ internal static unsafe void wstrcpy(char* dmem, char* smem, int charCount)
+ {
+ Buffer.Memmove((byte*)dmem, (byte*)smem, ((uint)charCount) * 2);
+ }
+
+
+ // Returns this string.
+ public override string ToString()
+ {
+ return this;
+ }
+
+ // Returns this string.
+ public string ToString(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ public CharEnumerator GetEnumerator()
+ {
+ return new CharEnumerator(this);
+ }
+
+ IEnumerator<char> IEnumerable<char>.GetEnumerator()
+ {
+ return new CharEnumerator(this);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new CharEnumerator(this);
+ }
+
+ internal static unsafe int wcslen(char* ptr)
+ {
+ char* end = ptr;
+
+ // First make sure our pointer is aligned on a word boundary
+ int alignment = IntPtr.Size - 1;
+
+ // If ptr is at an odd address (e.g. 0x5), this loop will simply iterate all the way
+ while (((uint)end & (uint)alignment) != 0)
+ {
+ if (*end == 0) goto FoundZero;
+ end++;
+ }
+
+#if !BIT64
+ // The following code is (somewhat surprisingly!) significantly faster than a naive loop,
+ // at least on x86 and the current jit.
+
+ // The loop condition below works because if "end[0] & end[1]" is non-zero, that means
+ // neither operand can have been zero. If is zero, we have to look at the operands individually,
+ // but we hope this going to fairly rare.
+
+ // In general, it would be incorrect to access end[1] if we haven't made sure
+ // end[0] is non-zero. However, we know the ptr has been aligned by the loop above
+ // so end[0] and end[1] must be in the same word (and therefore page), so they're either both accessible, or both not.
+
+ while ((end[0] & end[1]) != 0 || (end[0] != 0 && end[1] != 0))
+ {
+ end += 2;
+ }
+
+ Debug.Assert(end[0] == 0 || end[1] == 0);
+ if (end[0] != 0) end++;
+#else // !BIT64
+ // Based on https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
+
+ // 64-bit implementation: process 1 ulong (word) at a time
+
+ // What we do here is add 0x7fff from each of the
+ // 4 individual chars within the ulong, using MagicMask.
+ // If the char > 0 and < 0x8001, it will have its high bit set.
+ // We then OR with MagicMask, to set all the other bits.
+ // This will result in all bits set (ulong.MaxValue) for any
+ // char that fits the above criteria, and something else otherwise.
+
+ // Note that for any char > 0x8000, this will be a false
+ // positive and we will fallback to the slow path and
+ // check each char individually. This is OK though, since
+ // we optimize for the common case (ASCII chars, which are < 0x80).
+
+ // NOTE: We can access a ulong a time since the ptr is aligned,
+ // and therefore we're only accessing the same word/page. (See notes
+ // for the 32-bit version above.)
+
+ const ulong MagicMask = 0x7fff7fff7fff7fff;
+
+ while (true)
+ {
+ ulong word = *(ulong*)end;
+ word += MagicMask; // cause high bit to be set if not zero, and <= 0x8000
+ word |= MagicMask; // set everything besides the high bits
+
+ if (word == ulong.MaxValue) // 0xffff...
+ {
+ // all of the chars have their bits set (and therefore none can be 0)
+ end += 4;
+ continue;
+ }
+
+ // at least one of them didn't have their high bit set!
+ // go through each char and check for 0.
+
+ if (end[0] == 0) goto EndAt0;
+ if (end[1] == 0) goto EndAt1;
+ if (end[2] == 0) goto EndAt2;
+ if (end[3] == 0) goto EndAt3;
+
+ // if we reached here, it was a false positive-- just continue
+ end += 4;
+ }
+
+ EndAt3: end++;
+ EndAt2: end++;
+ EndAt1: end++;
+ EndAt0:
+#endif // !BIT64
+
+ FoundZero:
+ Debug.Assert(*end == 0);
+
+ int count = (int)(end - ptr);
+
+#if BIT64
+ // Check for overflow
+ if (ptr + count != end)
+ throw new ArgumentException(SR.Arg_MustBeNullTerminatedString);
+#else
+ Debug.Assert(ptr + count == end);
+#endif
+
+ return count;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode()
+ {
+ return TypeCode.String;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(this, provider);
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(this, provider);
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(this, provider);
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(this, provider);
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(this, provider);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(this, provider);
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(this, provider);
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(this, provider);
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(this, provider);
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(this, provider);
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(this, provider);
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(this, provider);
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(this, provider);
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ return Convert.ToDateTime(this, provider);
+ }
+
+ object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+
+ // Normalization Methods
+ // These just wrap calls to Normalization class
+ public bool IsNormalized()
+ {
+ return IsNormalized(NormalizationForm.FormC);
+ }
+
+ public bool IsNormalized(NormalizationForm normalizationForm)
+ {
+#if CORECLR
+ if (this.IsFastSort())
+ {
+ // If its FastSort && one of the 4 main forms, then its already normalized
+ if (normalizationForm == NormalizationForm.FormC ||
+ normalizationForm == NormalizationForm.FormKC ||
+ normalizationForm == NormalizationForm.FormD ||
+ normalizationForm == NormalizationForm.FormKD)
+ return true;
+ }
+#endif
+ return Normalization.IsNormalized(this, normalizationForm);
+ }
+
+ public string Normalize()
+ {
+ return Normalize(NormalizationForm.FormC);
+ }
+
+ public string Normalize(NormalizationForm normalizationForm)
+ {
+#if CORECLR
+ if (this.IsAscii())
+ {
+ // If its FastSort && one of the 4 main forms, then its already normalized
+ if (normalizationForm == NormalizationForm.FormC ||
+ normalizationForm == NormalizationForm.FormKC ||
+ normalizationForm == NormalizationForm.FormD ||
+ normalizationForm == NormalizationForm.FormKD)
+ return this;
+ }
+#endif
+ return Normalization.Normalize(this, normalizationForm);
+ }
+ }
+}
+
+#if MONO
+
+namespace System.Buffers
+{
+ public delegate void SpanAction<T, in TArg>(Span<T> span, TArg arg);
+ public delegate void ReadOnlySpanAction<T, in TArg>(ReadOnlySpan<T> span, TArg arg);
+}
+
+#endif
diff --git a/src/System.Private.CoreLib/shared/System/StringComparer.cs b/src/System.Private.CoreLib/shared/System/StringComparer.cs
index de311e91d..47731cb78 100644
--- a/src/System.Private.CoreLib/shared/System/StringComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/StringComparer.cs
@@ -114,10 +114,10 @@ namespace System
if (x == null) return -1;
if (y == null) return 1;
- String sa = x as String;
+ string sa = x as string;
if (sa != null)
{
- String sb = y as String;
+ string sb = y as string;
if (sb != null)
{
return Compare(sa, sb);
@@ -133,15 +133,15 @@ namespace System
throw new ArgumentException(SR.Argument_ImplementIComparable);
}
- public new bool Equals(Object x, Object y)
+ public new bool Equals(object x, object y)
{
if (x == y) return true;
if (x == null || y == null) return false;
- String sa = x as String;
+ string sa = x as string;
if (sa != null)
{
- String sb = y as String;
+ string sb = y as string;
if (sb != null)
{
return Equals(sa, sb);
@@ -165,8 +165,8 @@ namespace System
return obj.GetHashCode();
}
- public abstract int Compare(String x, String y);
- public abstract bool Equals(String x, String y);
+ public abstract int Compare(string x, string y);
+ public abstract bool Equals(string x, string y);
public abstract int GetHashCode(string obj);
}
@@ -293,7 +293,7 @@ namespace System
{
return false;
}
- return (string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
+ return string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
}
return x.Equals(y);
}
@@ -307,7 +307,7 @@ namespace System
if (_ignoreCase)
{
- return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
+ return CompareInfo.GetIgnoreCaseHash(obj);
}
return obj.GetHashCode();
@@ -375,7 +375,7 @@ namespace System
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
}
- return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
+ return CompareInfo.GetIgnoreCaseHash(obj);
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
diff --git a/src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs b/src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs
deleted file mode 100644
index 9ddcc9450..000000000
--- a/src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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.Globalization;
-
-namespace System
-{
- /// <summary>Helpers for string-like operations on spans of chars.</summary>
- internal static class StringSpanHelpers
- {
- // TODO https://github.com/dotnet/corefx/issues/21395: Provide public, efficient implementations
-
- public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right, StringComparison comparisonType) =>
- comparisonType == StringComparison.Ordinal ? Equals(left, right) :
- comparisonType == StringComparison.OrdinalIgnoreCase ? EqualsOrdinalIgnoreCase(left, right) :
- throw new ArgumentOutOfRangeException(nameof(comparisonType));
-
- public static bool Equals(this ReadOnlySpan<char> left, string right) =>
- Equals(left, right.AsSpan());
-
- public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
- {
- if (left.Length != right.Length)
- {
- return false;
- }
-
- for (int i = 0; i < left.Length; i++)
- {
- if (left[i] != right[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
-#if MONO
- internal
-#endif
- static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
- {
- if (left.Length != right.Length)
- {
- return false;
- }
-
- for (int i = 0; i < left.Length; i++)
- {
- char x = left[i], y = right[i];
- if (x != y &&
- TextInfo.ToUpperAsciiInvariant(x) != TextInfo.ToUpperAsciiInvariant(y))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static int IndexOf(this ReadOnlySpan<char> source, char value) =>
- IndexOf(source, value, 0);
-
- public static int IndexOf(this ReadOnlySpan<char> source, char value, int startIndex)
- {
- for (int i = startIndex; i < source.Length; i++)
- {
- if (source[i] == value)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- public static bool Contains(this ReadOnlySpan<char> source, char value)
- {
- for (int i = 0; i < source.Length; i++)
- {
- if (source[i] == value)
- {
- return true;
- }
- }
-
- return false;
- }
-
- public static ReadOnlySpan<char> Remove(this ReadOnlySpan<char> source, int startIndex, int count)
- {
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
- if (count < 0)
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
- if (count > source.Length - startIndex)
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_IndexCount);
-
- if (count == 0)
- {
- return source;
- }
-
- int newLength = source.Length - count;
- if (newLength == 0)
- {
- return ReadOnlySpan<char>.Empty;
- }
-
- Span<char> result = new char[newLength];
- source.Slice(0, startIndex).CopyTo(result);
- source.Slice(startIndex + count).CopyTo(result.Slice(startIndex));
- return result;
- }
-
- // Returns the index of the last occurrence of a specified character in the current instance.
- public static int LastIndexOf(this ReadOnlySpan<char> source, char value)
- {
- if (source.Length == 0)
- return -1;
-
- for (int i = source.Length - 1; i >= 0; i--)
- {
- if (source[i] == value)
- return i;
- }
-
- return -1;
- }
-
- public static void CheckStringComparison(StringComparison comparisonType)
- {
- // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
- if ((uint)(comparisonType - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
- {
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
- }
- }
- }
-}
diff --git a/src/System.Private.CoreLib/shared/System/SystemException.cs b/src/System.Private.CoreLib/shared/System/SystemException.cs
index b7e8e4217..9a1daf210 100644
--- a/src/System.Private.CoreLib/shared/System/SystemException.cs
+++ b/src/System.Private.CoreLib/shared/System/SystemException.cs
@@ -16,13 +16,13 @@ namespace System
HResult = HResults.COR_E_SYSTEM;
}
- public SystemException(String message)
+ public SystemException(string message)
: base(message)
{
HResult = HResults.COR_E_SYSTEM;
}
- public SystemException(String message, Exception innerException)
+ public SystemException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_SYSTEM;
diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
index e89943a19..217d93467 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
@@ -31,7 +31,7 @@ namespace System.Text
{
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For ASCIIEncoding we just use default replacement fallback
this.encoderFallback = EncoderFallback.ReplacementFallback;
@@ -59,13 +59,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -81,11 +81,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String chars)
+ public override unsafe int GetByteCount(string chars)
{
// Validate input
if (chars==null)
- throw new ArgumentNullException("chars");
+ throw new ArgumentNullException(nameof(chars));
fixed (char* pChars = chars)
return GetByteCount(pChars, chars.Length, null);
@@ -100,34 +100,42 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
+ public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetByteCount(charsPtr, chars.Length, encoder: null);
+ }
+ }
+
// Parent method is safe.
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String chars, int charIndex, int charCount,
+ public override unsafe int GetBytes(string chars, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -154,16 +162,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0
if (charCount == 0)
@@ -186,14 +194,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
+ public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, encoder: null);
+ }
+ }
+
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
//
@@ -206,13 +223,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -232,14 +249,22 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
+ public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetCharCount(bytesPtr, bytes.Length, decoder: null);
+ }
+ }
+
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
@@ -250,16 +275,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -282,14 +307,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
+ public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, decoder: null);
+ }
+ }
+
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
//
@@ -298,24 +332,24 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int byteIndex, int byteCount)
+ public override unsafe string GetString(byte[] bytes, int byteIndex, int byteCount)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (byteCount == 0) return String.Empty;
+ if (byteCount == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + byteIndex, byteCount, this);
}
@@ -326,7 +360,7 @@ namespace System.Text
// GetByteCount
// Note: We start by assuming that the output will be the same as count. Having
// an encoder or fallback may change that assumption
- internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative");
@@ -348,7 +382,7 @@ namespace System.Text
if (encoder != null)
{
charLeftOver = encoder._charLeftOver;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
@@ -400,7 +434,7 @@ namespace System.Text
// We may have a left over character from last time, try and process it.
if (charLeftOver > 0)
{
- Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
+ Debug.Assert(char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
Debug.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");
// Since left over char was a surrogate, it'll have to be fallen back.
@@ -460,8 +494,8 @@ namespace System.Text
return byteCount;
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null");
@@ -502,7 +536,7 @@ namespace System.Text
fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
}
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[ASCIIEncoding.GetBytes]leftover character should be high surrogate");
// Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
@@ -676,7 +710,7 @@ namespace System.Text
}
// This is internal and called by something else,
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
{
// Just assert, we're called internally so these should be safe, checked already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null");
@@ -748,8 +782,8 @@ namespace System.Text
return charCount;
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS decoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null");
diff --git a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
index b827648fc..b4a7575ba 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
@@ -134,7 +134,7 @@ namespace System.Text
public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes, bool flush)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetCharCount(bytesPtr, bytes.Length, flush);
}
@@ -227,8 +227,8 @@ namespace System.Text
public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, flush);
}
@@ -341,8 +341,8 @@ namespace System.Text
public virtual unsafe void Convert(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush, out int bytesUsed, out int charsUsed, out bool completed)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
Convert(bytesPtr, bytes.Length, charsPtr, chars.Length, flush, out bytesUsed, out charsUsed, out completed);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
index 30c817c91..8c62730c2 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
@@ -38,7 +38,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
InternalDecoderBestFitFallback that = value as InternalDecoderBestFitFallback;
if (that != null)
@@ -63,15 +63,15 @@ namespace System.Text
private InternalDecoderBestFitFallback _oFallback;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
index 8bfc1f32d..56c004714 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
@@ -29,7 +29,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderExceptionFallback that = value as DecoderExceptionFallback;
if (that != null)
@@ -112,19 +112,19 @@ namespace System.Text
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message)
+ public DecoderFallbackException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message, Exception innerException)
+ public DecoderFallbackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message, byte[] bytesUnknown, int index)
+ public DecoderFallbackException(string message, byte[] bytesUnknown, int index)
: base(message)
{
_bytesUnknown = bytesUnknown;
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
index 11b9539b5..fff8ad1d7 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
@@ -104,9 +104,9 @@ namespace System.Text
while ((ch = GetNextChar()) != 0)
{
// Make sure no mixed up surrogates
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
{
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// High Surrogate
if (bHighSurrogate)
@@ -159,9 +159,9 @@ namespace System.Text
while ((ch = GetNextChar()) != 0)
{
// Make sure no mixed up surrogates
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
{
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// High Surrogate
if (bHighSurrogate)
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
index 422b80bb2..a97baf05c 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
@@ -9,14 +9,14 @@ namespace System.Text
public sealed class DecoderReplacementFallback : DecoderFallback
{
// Our variables
- private String _strDefault;
+ private string _strDefault;
// Construction. Default replacement fallback uses no best fit and ? replacement string
public DecoderReplacementFallback() : this("?")
{
}
- public DecoderReplacementFallback(String replacement)
+ public DecoderReplacementFallback(string replacement)
{
if (replacement == null)
throw new ArgumentNullException(nameof(replacement));
@@ -26,10 +26,10 @@ namespace System.Text
for (int i = 0; i < replacement.Length; i++)
{
// Found a surrogate?
- if (Char.IsSurrogate(replacement, i))
+ if (char.IsSurrogate(replacement, i))
{
// High or Low?
- if (Char.IsHighSurrogate(replacement, i))
+ if (char.IsHighSurrogate(replacement, i))
{
// if already had a high one, stop
if (bFoundHigh)
@@ -60,7 +60,7 @@ namespace System.Text
_strDefault = replacement;
}
- public String DefaultString
+ public string DefaultString
{
get
{
@@ -82,7 +82,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderReplacementFallback that = value as DecoderReplacementFallback;
if (that != null)
@@ -103,7 +103,7 @@ namespace System.Text
public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer
{
// Store our default string
- private String _strDefault;
+ private string _strDefault;
private int _fallbackCount = -1;
private int _fallbackIndex = -1;
diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
index fb1bdb803..df7d51203 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
@@ -132,7 +132,7 @@ namespace System.Text
public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars, bool flush)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetByteCount(charsPtr, chars.Length, flush);
}
@@ -221,8 +221,8 @@ namespace System.Text
public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, flush);
}
@@ -335,8 +335,8 @@ namespace System.Text
public virtual unsafe void Convert(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush, out int charsUsed, out int bytesUsed, out bool completed)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
Convert(charsPtr, chars.Length, bytesPtr, bytes.Length, flush, out charsUsed, out bytesUsed, out completed);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
index 7f3be2a7a..4aab3f62a 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
@@ -38,7 +38,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
InternalEncoderBestFitFallback that = value as InternalEncoderBestFitFallback;
if (that != null)
@@ -63,15 +63,15 @@ namespace System.Text
private int _iSize;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
@@ -113,12 +113,12 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Double check input surrogate pair
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range,
0xD800, 0xDBFF));
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range,
0xDC00, 0xDFFF));
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
index 66de1940f..92afcf701 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
@@ -28,7 +28,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncoderExceptionFallback that = value as EncoderExceptionFallback;
if (that != null)
@@ -57,18 +57,18 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
}
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
}
- int iTemp = Char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
+ int iTemp = char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
// Fall back our char
throw new EncoderFallbackException(
@@ -111,34 +111,34 @@ namespace System.Text
HResult = HResults.COR_E_ARGUMENT;
}
- public EncoderFallbackException(String message)
+ public EncoderFallbackException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public EncoderFallbackException(String message, Exception innerException)
+ public EncoderFallbackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
internal EncoderFallbackException(
- String message, char charUnknown, int index) : base(message)
+ string message, char charUnknown, int index) : base(message)
{
_charUnknown = charUnknown;
_index = index;
}
internal EncoderFallbackException(
- String message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
+ string message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
{
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
}
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException(nameof(CharUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
index d860a02a7..f98b15e07 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
@@ -142,7 +142,7 @@ namespace System.Text
int index = (int)(chars - charStart) - 1;
// See if it was a high surrogate
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// See if there's a low surrogate to go with it
if (chars >= this.charEnd)
@@ -165,11 +165,11 @@ namespace System.Text
{
// Might have a low surrogate
char cNext = *chars;
- if (Char.IsLowSurrogate(cNext))
+ if (char.IsLowSurrogate(cNext))
{
// If already falling back then fail
if (bFallingBack && iRecursionCount++ > iMaxRecursion)
- ThrowLastCharRecursive(Char.ConvertToUtf32(ch, cNext));
+ ThrowLastCharRecursive(char.ConvertToUtf32(ch, cNext));
// Next is a surrogate, add it as surrogate pair, and increment chars
chars++;
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
index a1d0bbcd9..760c280fd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
@@ -11,14 +11,14 @@ namespace System.Text
public sealed class EncoderReplacementFallback : EncoderFallback
{
// Our variables
- private String _strDefault;
+ private string _strDefault;
// Construction. Default replacement fallback uses no best fit and ? replacement string
public EncoderReplacementFallback() : this("?")
{
}
- public EncoderReplacementFallback(String replacement)
+ public EncoderReplacementFallback(string replacement)
{
// Must not be null
if (replacement == null)
@@ -29,10 +29,10 @@ namespace System.Text
for (int i = 0; i < replacement.Length; i++)
{
// Found a surrogate?
- if (Char.IsSurrogate(replacement, i))
+ if (char.IsSurrogate(replacement, i))
{
// High or Low?
- if (Char.IsHighSurrogate(replacement, i))
+ if (char.IsHighSurrogate(replacement, i))
{
// if already had a high one, stop
if (bFoundHigh)
@@ -63,7 +63,7 @@ namespace System.Text
_strDefault = replacement;
}
- public String DefaultString
+ public string DefaultString
{
get
{
@@ -85,7 +85,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncoderReplacementFallback that = value as EncoderReplacementFallback;
if (that != null)
@@ -106,7 +106,7 @@ namespace System.Text
public sealed class EncoderReplacementFallbackBuffer : EncoderFallbackBuffer
{
// Store our default string
- private String _strDefault;
+ private string _strDefault;
private int _fallbackCount = -1;
private int _fallbackIndex = -1;
@@ -127,7 +127,7 @@ namespace System.Text
// If we're recursive we may still have something in our buffer that makes this a surrogate
if (char.IsHighSurrogate(charUnknown) && _fallbackCount >= 0 &&
char.IsLowSurrogate(_strDefault[_fallbackIndex + 1]))
- ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
+ ThrowLastCharRecursive(char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
// Nope, just one character
ThrowLastCharRecursive(unchecked((int)charUnknown));
@@ -144,18 +144,18 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Double check input surrogate pair
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
// If we had a buffer already we're being recursive, throw, it's probably at the suspect
// character in our array.
if (_fallbackCount >= 1)
- ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
+ ThrowLastCharRecursive(char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
// Go ahead and get our fallback
_fallbackCount = _strDefault.Length;
diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
index e469180ce..005f08afd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
@@ -325,7 +325,7 @@ namespace System.Text
// Returns an Encoding object for a given name or a given code page value.
//
- public static Encoding GetEncoding(String name)
+ public static Encoding GetEncoding(string name)
{
Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name);
if (baseEncoding != null)
@@ -342,7 +342,7 @@ namespace System.Text
// Returns an Encoding object for a given name or a given code page value.
//
- public static Encoding GetEncoding(String name,
+ public static Encoding GetEncoding(string name,
EncoderFallback encoderFallback, DecoderFallback decoderFallback)
{
Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name, encoderFallback, decoderFallback);
@@ -386,7 +386,7 @@ namespace System.Text
// Returns the name for this encoding that can be used with mail agent body tags.
// If the encoding may not be used, the string is empty.
- public virtual String BodyName
+ public virtual string BodyName
{
get
{
@@ -443,7 +443,7 @@ namespace System.Text
}
}
#else
- public virtual String EncodingName
+ public virtual string EncodingName
{
get
{
@@ -454,7 +454,7 @@ namespace System.Text
// Returns the name for this encoding that can be used with mail agent header
// tags. If the encoding may not be used, the string is empty.
- public virtual String HeaderName
+ public virtual string HeaderName
{
get
{
@@ -467,7 +467,7 @@ namespace System.Text
}
// Returns the IANA preferred name for this encoding.
- public virtual String WebName
+ public virtual string WebName
{
get
{
@@ -603,7 +603,7 @@ namespace System.Text
}
- public virtual Object Clone()
+ public virtual object Clone()
{
Encoding newEncoding = (Encoding)this.MemberwiseClone();
@@ -646,7 +646,7 @@ namespace System.Text
return GetByteCount(chars, 0, chars.Length);
}
- public virtual int GetByteCount(String s)
+ public virtual int GetByteCount(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -713,7 +713,7 @@ namespace System.Text
public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetByteCount(charsPtr, chars.Length);
}
@@ -767,7 +767,7 @@ namespace System.Text
// Returns a byte array containing the encoded representation of the given
// string.
//
- public virtual byte[] GetBytes(String s)
+ public virtual byte[] GetBytes(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s),
@@ -817,7 +817,7 @@ namespace System.Text
}
}
- public virtual int GetBytes(String s, int charIndex, int charCount,
+ public virtual int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null)
@@ -895,8 +895,8 @@ namespace System.Text
public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
}
@@ -945,7 +945,7 @@ namespace System.Text
public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetCharCount(bytesPtr, bytes.Length);
}
@@ -1057,8 +1057,8 @@ namespace System.Text
public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length);
}
@@ -1082,14 +1082,14 @@ namespace System.Text
if (byteCount < 0)
throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
- return String.CreateStringFromEncoding(bytes, byteCount, this);
+ return string.CreateStringFromEncoding(bytes, byteCount, this);
}
public unsafe string GetString(ReadOnlySpan<byte> bytes)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
- return GetString(bytesPtr, bytes.Length);
+ return string.CreateStringFromEncoding(bytesPtr, bytes.Length, this);
}
}
@@ -1184,7 +1184,7 @@ namespace System.Text
// Returns a string containing the decoded representation of a given byte
// array.
//
- public virtual String GetString(byte[] bytes)
+ public virtual string GetString(byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes),
@@ -1198,9 +1198,9 @@ namespace System.Text
//
// Internally we override this for performance
//
- public virtual String GetString(byte[] bytes, int index, int count)
+ public virtual string GetString(byte[] bytes, int index, int count)
{
- return new String(GetChars(bytes, index, count));
+ return new string(GetChars(bytes, index, count));
}
// Returns an encoding for Unicode format. The returned encoding will be
@@ -1241,7 +1241,7 @@ namespace System.Text
private static Encoding BigEndianUTF32 => UTF32Encoding.s_bigEndianDefault;
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
Encoding that = value as Encoding;
if (that != null)
@@ -1325,7 +1325,7 @@ namespace System.Text
_encoding = encoding;
}
- public Object GetRealObject(StreamingContext context)
+ public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
}
@@ -1390,7 +1390,7 @@ namespace System.Text
_encoding = encoding;
}
- public Object GetRealObject(StreamingContext context)
+ public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
index 99995f759..8e71e58fa 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
@@ -53,7 +53,7 @@ namespace System.Text
return Encoding.GetEncoding(iCodePage);
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncodingInfo that = value as EncodingInfo;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
index d5de9e553..e6fa0627d 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
@@ -40,13 +40,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -61,11 +61,11 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -78,10 +78,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -91,20 +91,20 @@ namespace System.Text
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -130,16 +130,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -160,10 +160,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -179,13 +179,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -203,10 +203,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -220,16 +220,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -250,10 +250,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -265,23 +265,23 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
index ce8c3e020..4d15eea01 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
@@ -130,7 +130,7 @@ namespace System.Text
return null;
}
- private static Object s_InternalSyncObject = new Object();
+ private static object s_InternalSyncObject = new object();
private static volatile EncodingProvider[] s_providers;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
index 335eb76e3..736fff5d2 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
@@ -11,7 +11,7 @@ namespace System.Text
// Latin1Encoding is a simple override to optimize the GetString version of Latin1Encoding.
// because of the best fit cases we can't do this when encoding the string, only when decoding
//
- internal class Latin1Encoding : EncodingNLS
+ internal sealed class Latin1Encoding : EncodingNLS
{
// Used by Encoding.Latin1 for lazy initialization
// The initialization code will not be run until a static member of the class is referenced
@@ -42,7 +42,7 @@ namespace System.Text
if (encoder != null)
{
charLeftOver = encoder._charLeftOver;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
@@ -164,7 +164,7 @@ namespace System.Text
{
charLeftOver = encoder._charLeftOver;
fallback = encoder.Fallback as EncoderReplacementFallback;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetBytes]leftover character should be high surrogate");
// Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
new file mode 100644
index 000000000..a62c4777a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
@@ -0,0 +1,37 @@
+// 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.Diagnostics;
+
+namespace System.Text
+{
+ public sealed partial class StringBuilder
+ {
+ private void ShowChunks(int maxChunksToShow = 10)
+ {
+ int count = 0;
+ StringBuilder head = this, current = this;
+ while (current != null)
+ {
+ if (count < maxChunksToShow)
+ {
+ count++;
+ }
+ else
+ {
+ head = head.m_ChunkPrevious;
+ }
+ current = current.m_ChunkPrevious;
+ }
+ current = head;
+ string[] chunks = new string[count];
+ for (int i = count; i > 0; i--)
+ {
+ chunks[i - 1] = new string(current.m_ChunkChars).Replace('\0', '.');
+ current = current.m_ChunkPrevious;
+ }
+ Debug.WriteLine('|' + string.Join('|', chunks) + '|');
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
index a7804c399..99021e2dd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
@@ -18,10 +18,10 @@ using System.Collections.Generic;
namespace System.Text
{
// This class represents a mutable string. It is convenient for situations in
- // which it is desirable to modify a string, perhaps by removing, replacing, or
+ // which it is desirable to modify a string, perhaps by removing, replacing, or
// inserting characters, without creating a new String subsequent to
- // each modification.
- //
+ // each modification.
+ //
// The methods contained within this class do not return a new StringBuilder
// object unless specified otherwise. This class may be used in conjunction with the String
// class to carry out modifications upon strings.
@@ -30,8 +30,8 @@ namespace System.Text
public sealed partial class StringBuilder : ISerializable
{
// A StringBuilder is internally represented as a linked list of blocks each of which holds
- // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
- // so that is what we do.
+ // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
+ // so that is what we do.
/// <summary>
/// The character buffer for this chunk.
@@ -73,7 +73,7 @@ namespace System.Text
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
// Making the maximum chunk size big means less allocation code called, but also more waste
// in unused characters and slower inserts / replaces (since you do need to slide characters over
- // within a buffer).
+ // within a buffer).
internal const int MaxChunkSize = 8000;
/// <summary>
@@ -201,7 +201,7 @@ namespace System.Text
int persistedCapacity = 0;
string persistedString = null;
- int persistedMaxCapacity = Int32.MaxValue;
+ int persistedMaxCapacity = int.MaxValue;
bool capacityPresent = false;
// Get the data
@@ -353,7 +353,7 @@ namespace System.Text
return Capacity;
}
- public override String ToString()
+ public override string ToString()
{
AssertInvariants();
@@ -377,7 +377,7 @@ namespace System.Text
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
- // Check that we will not overrun our boundaries.
+ // Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= (uint)result.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
fixed (char* sourcePtr = &sourceArray[0])
@@ -462,13 +462,10 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_SmallCapacity);
}
- int originalCapacity = Capacity;
-
if (value == 0 && m_ChunkPrevious == null)
{
m_ChunkLength = 0;
m_ChunkOffset = 0;
- Debug.Assert(Capacity >= originalCapacity);
return;
}
@@ -483,22 +480,32 @@ namespace System.Text
StringBuilder chunk = FindChunkForIndex(value);
if (chunk != this)
{
- // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
- // to ensure the original capacity is preserved.
- int newLen = originalCapacity - chunk.m_ChunkOffset;
- char[] newArray = new char[newLen];
-
- Debug.Assert(newLen > chunk.m_ChunkChars.Length, "The new chunk should be larger than the one it is replacing.");
- Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength);
+ // Avoid possible infinite capacity growth. See https://github.com/dotnet/coreclr/pull/16926
+ int capacityToPreserve = Math.Min(Capacity, Math.Max(Length * 6 / 5, m_ChunkChars.Length));
+ int newLen = capacityToPreserve - chunk.m_ChunkOffset;
+ if (newLen > chunk.m_ChunkChars.Length)
+ {
+ // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
+ // to ensure the capacity we want is preserved.
+ char[] newArray = new char[newLen];
+ Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength);
+ m_ChunkChars = newArray;
+ }
+ else
+ {
+ // Special case where the capacity we want to keep corresponds exactly to the size of the content.
+ // Just take ownership of the array.
+ Debug.Assert(newLen == chunk.m_ChunkChars.Length, "The new chunk should be larger or equal to the one it is replacing.");
+ m_ChunkChars = chunk.m_ChunkChars;
+ }
- m_ChunkChars = newArray;
m_ChunkPrevious = chunk.m_ChunkPrevious;
m_ChunkOffset = chunk.m_ChunkOffset;
}
m_ChunkLength = value - chunk.m_ChunkOffset;
AssertInvariants();
}
- Debug.Assert(Capacity >= originalCapacity);
+ Debug.Assert(Length == value, "Something went wrong setting Length.");
}
}
@@ -551,6 +558,138 @@ namespace System.Text
}
/// <summary>
+ /// GetChunks returns ChunkEnumerator that follows the IEnumerable pattern and
+ /// thus can be used in a C# 'foreach' statements to retreive the data in the StringBuilder
+ /// as chunks (ReadOnlyMemory) of characters. An example use is:
+ ///
+ /// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ /// foreach(char c in chunk.Span)
+ /// { /* operation on c }
+ ///
+ /// It is undefined what happens if the StringBuilder is modified while the chunk
+ /// enumeration is incomplete. StringBuilder is also not thread-safe, so operating
+ /// on it with concurrent threads is illegal. Finally the ReadOnlyMemory chunks returned
+ /// are NOT guarenteed to remain unchanged if the StringBuilder is modified, so do
+ /// not cache them for later use either. This API's purpose is efficiently extracting
+ /// the data of a CONSTANT StringBuilder.
+ ///
+ /// Creating a ReadOnlySpan from a ReadOnlyMemory (the .Span property) is expensive
+ /// compared to the fetching of the character, so create a local variable for the SPAN
+ /// if you need to use it in a nested for statement. For example
+ ///
+ /// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ /// {
+ /// var span = chunk.Span;
+ /// for(int i = 0; i < span.Length; i++)
+ /// { /* operation on span[i] */ }
+ /// }
+ /// </summary>
+ public ChunkEnumerator GetChunks() => new ChunkEnumerator(this);
+
+ /// <summary>
+ /// ChunkEnumerator supports both the IEnumerable and IEnumerator pattern so foreach
+ /// works (see GetChunks). It needs to be public (so the compiler can use it
+ /// when building a foreach statement) but users typically don't use it explicitly.
+ /// (which is why it is a nested type).
+ /// </summary>
+ public struct ChunkEnumerator
+ {
+ private readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string)
+ private StringBuilder _currentChunk; // The chunk that this enumerator is currently returning (Current).
+ private readonly ManyChunkInfo _manyChunks; // Only used for long string builders with many chunks (see constructor)
+
+ /// <summary>
+ /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator
+ /// </summary>
+ [ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)] // Only here to make foreach work
+ public ChunkEnumerator GetEnumerator() { return this; }
+
+ /// <summary>
+ /// Implements the IEnumerator pattern.
+ /// </summary>
+ public bool MoveNext()
+ {
+ if (_currentChunk == _firstChunk)
+ return false;
+
+ if (_manyChunks != null)
+ return _manyChunks.MoveNext(ref _currentChunk);
+
+ StringBuilder next = _firstChunk;
+ while (next.m_ChunkPrevious != _currentChunk)
+ next = next.m_ChunkPrevious;
+ _currentChunk = next;
+ return true;
+ }
+
+ /// <summary>
+ /// Implements the IEnumerator pattern.
+ /// </summary>
+ public ReadOnlyMemory<char> Current => new ReadOnlyMemory<char>(_currentChunk.m_ChunkChars, 0, _currentChunk.m_ChunkLength);
+
+ #region private
+ internal ChunkEnumerator(StringBuilder stringBuilder)
+ {
+ Debug.Assert(stringBuilder != null);
+ _firstChunk = stringBuilder;
+ _currentChunk = null; // MoveNext will find the last chunk if we do this.
+ _manyChunks = null;
+
+ // There is a performance-vs-allocation tradeoff. Because the chunks
+ // are a linked list with each chunk pointing to its PREDECESSOR, walking
+ // the list FORWARD is not efficient. If there are few chunks (< 8) we
+ // simply scan from the start each time, and tolerate the N*N behavior.
+ // However above this size, we allocate an array to hold pointers to all
+ // the chunks and we can be efficient for large N.
+ int chunkCount = ChunkCount(stringBuilder);
+ if (8 < chunkCount)
+ _manyChunks = new ManyChunkInfo(stringBuilder, chunkCount);
+ }
+
+ private static int ChunkCount(StringBuilder stringBuilder)
+ {
+ int ret = 0;
+ while (stringBuilder != null)
+ {
+ ret++;
+ stringBuilder = stringBuilder.m_ChunkPrevious;
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Used to hold all the chunks indexes when you have many chunks.
+ /// </summary>
+ private class ManyChunkInfo
+ {
+ private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first)
+ private int _chunkPos;
+
+ public bool MoveNext(ref StringBuilder current)
+ {
+ int pos = ++_chunkPos;
+ if (_chunks.Length <= pos)
+ return false;
+ current = _chunks[pos];
+ return true;
+ }
+
+ public ManyChunkInfo(StringBuilder stringBuilder, int chunkCount)
+ {
+ _chunks = new StringBuilder[chunkCount];
+ while (0 <= --chunkCount)
+ {
+ Debug.Assert(stringBuilder != null);
+ _chunks[chunkCount] = stringBuilder;
+ stringBuilder = stringBuilder.m_ChunkPrevious;
+ }
+ _chunkPos = -1;
+ }
+ }
+#endregion
+ }
+
+ /// <summary>
/// Appends a character 0 or more times to the end of this builder.
/// </summary>
/// <param name="value">The character to append.</param>
@@ -648,7 +787,7 @@ namespace System.Text
/// Appends a string to the end of this builder.
/// </summary>
/// <param name="value">The string to append.</param>
- public StringBuilder Append(String value)
+ public StringBuilder Append(string value)
{
if (value != null)
{
@@ -691,7 +830,7 @@ namespace System.Text
}
// We put this fixed in its own helper to avoid the cost of zero-initing `valueChars` in the
- // case we don't actually use it.
+ // case we don't actually use it.
private void AppendHelper(string value)
{
unsafe
@@ -903,7 +1042,7 @@ namespace System.Text
/// <param name="index">The index to insert in this builder.</param>
/// <param name="value">The string to insert.</param>
/// <param name="count">The number of times to insert the string.</param>
- public StringBuilder Insert(int index, String value, int count)
+ public StringBuilder Insert(int index, string value, int count)
{
if (count < 0)
{
@@ -921,7 +1060,7 @@ namespace System.Text
return this;
}
- // Ensure we don't insert more chars than we can hold, and we don't
+ // Ensure we don't insert more chars than we can hold, and we don't
// have any integer overflow in our new length.
long insertingChars = (long)value.Length * count;
if (insertingChars > MaxCapacity - this.Length)
@@ -1115,7 +1254,7 @@ namespace System.Text
{
return AppendJoinCore(&separator, 1, values);
}
-
+
private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, IEnumerable<T> values)
{
Debug.Assert(separator != null);
@@ -1182,7 +1321,7 @@ namespace System.Text
#endregion
- public StringBuilder Insert(int index, String value)
+ public StringBuilder Insert(int index, string value)
{
if ((uint)index > (uint)Length)
{
@@ -1292,7 +1431,7 @@ namespace System.Text
[CLSCompliant(false)]
public StringBuilder Insert(int index, ulong value) => Insert(index, value.ToString(), 1);
- public StringBuilder Insert(int index, Object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
+ public StringBuilder Insert(int index, object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
public StringBuilder Insert(int index, ReadOnlySpan<char> value)
{
@@ -1312,13 +1451,13 @@ namespace System.Text
return this;
}
- public StringBuilder AppendFormat(String format, Object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0));
+ public StringBuilder AppendFormat(string format, object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0));
- public StringBuilder AppendFormat(String format, Object arg0, Object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
+ public StringBuilder AppendFormat(string format, object arg0, object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
- public StringBuilder AppendFormat(String format, Object arg0, Object arg1, Object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
+ public StringBuilder AppendFormat(string format, object arg0, object arg1, object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
- public StringBuilder AppendFormat(String format, params Object[] args)
+ public StringBuilder AppendFormat(string format, params object[] args)
{
if (args == null)
{
@@ -1331,13 +1470,13 @@ namespace System.Text
return AppendFormatHelper(null, format, new ParamsArray(args));
}
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1, Object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1, object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, params Object[] args)
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args)
{
if (args == null)
{
@@ -1359,7 +1498,7 @@ namespace System.Text
private const int IndexLimit = 1000000; // Note: 0 <= ArgIndex < IndexLimit
private const int WidthLimit = 1000000; // Note: -WidthLimit < ArgAlign < WidthLimit
- internal StringBuilder AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
+ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string format, ParamsArray args)
{
if (format == null)
{
@@ -1495,8 +1634,8 @@ namespace System.Text
//
// Start of parsing of optional formatting parameter.
//
- Object arg = args[index];
- String itemFormat = null;
+ object arg = args[index];
+ string itemFormat = null;
ReadOnlySpan<char> itemFormatSpan = default; // used if itemFormat is null
// Is current character a colon? which indicates start of formatting parameter.
if (ch == ':')
@@ -1552,7 +1691,7 @@ namespace System.Text
if (startPos != pos)
{
// There was no brace escaping, extract the item format as a single string
- itemFormatSpan = format.AsSpan().Slice(startPos, pos - startPos);
+ itemFormatSpan = format.AsSpan(startPos, pos - startPos);
}
}
else
@@ -1566,7 +1705,7 @@ namespace System.Text
if (ch != '}') FormatError();
// Construct the output for this arg hole.
pos++;
- String s = null;
+ string s = null;
if (cf != null)
{
if (itemFormatSpan.Length != 0 && itemFormat == null)
@@ -1609,7 +1748,7 @@ namespace System.Text
}
}
// Append it to the final output of the Format String.
- if (s == null) s = String.Empty;
+ if (s == null) s = string.Empty;
int pad = width - s.Length;
if (!leftJustify && pad > 0) Append(' ', pad);
Append(s);
@@ -1628,7 +1767,7 @@ namespace System.Text
/// If <paramref name="newValue"/> is <c>null</c>, instances of <paramref name="oldValue"/>
/// are removed from this builder.
/// </remarks>
- public StringBuilder Replace(String oldValue, String newValue) => Replace(oldValue, newValue, 0, Length);
+ public StringBuilder Replace(string oldValue, string newValue) => Replace(oldValue, newValue, 0, Length);
/// <summary>
/// Determines if the contents of this builder are equal to the contents of another builder.
@@ -1680,10 +1819,10 @@ namespace System.Text
/// <summary>
/// Determines if the contents of this builder are equal to the contents of ReadOnlySpan<char>.
/// </summary>
- /// <param name="value">The ReadOnlySpan{char}.</param>
- public bool Equals(ReadOnlySpan<char> value)
+ /// <param name="span">The ReadOnlySpan{char}.</param>
+ public bool Equals(ReadOnlySpan<char> span)
{
- if (value.Length != Length)
+ if (span.Length != Length)
return false;
StringBuilder sbChunk = this;
@@ -1696,7 +1835,7 @@ namespace System.Text
ReadOnlySpan<char> chunk = new ReadOnlySpan<char>(sbChunk.m_ChunkChars, 0, chunk_length);
- if (!chunk.Equals(value.Slice(value.Length - offset, chunk_length)))
+ if (!chunk.EqualsOrdinal(span.Slice(span.Length - offset, chunk_length)))
return false;
sbChunk = sbChunk.m_ChunkPrevious;
@@ -1717,7 +1856,7 @@ namespace System.Text
/// If <paramref name="newValue"/> is <c>null</c>, instances of <paramref name="oldValue"/>
/// are removed from this builder.
/// </remarks>
- public StringBuilder Replace(String oldValue, String newValue, int startIndex, int count)
+ public StringBuilder Replace(string oldValue, string newValue, int startIndex, int count)
{
int currentLength = Length;
if ((uint)startIndex > (uint)currentLength)
@@ -1749,7 +1888,7 @@ namespace System.Text
int indexInChunk = startIndex - chunk.m_ChunkOffset;
while (count > 0)
{
- // Look for a match in the chunk,indexInChunk pointer
+ // Look for a match in the chunk,indexInChunk pointer
if (StartsWith(chunk, indexInChunk, count, oldValue))
{
// Push it on the replacements array (with growth), we will do all replacements in a
@@ -1775,13 +1914,13 @@ namespace System.Text
if (indexInChunk >= chunk.m_ChunkLength || count == 0) // Have we moved out of the current chunk?
{
- // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
+ // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
int index = indexInChunk + chunk.m_ChunkOffset;
int indexBeforeAdjustment = index;
// See if we accumulated any replacements, if so apply them.
ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue);
- // The replacement has affected the logical index. Adjust it.
+ // The replacement has affected the logical index. Adjust it.
index += ((newValue.Length - oldValue.Length) * replacementsCount);
replacementsCount = 0;
@@ -1874,7 +2013,7 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(valueCount), SR.ArgumentOutOfRange_LengthGreaterThanCapacity);
}
- // This case is so common we want to optimize for it heavily.
+ // This case is so common we want to optimize for it heavily.
int newIndex = valueCount + m_ChunkLength;
if (newIndex <= m_ChunkChars.Length)
{
@@ -1891,7 +2030,7 @@ namespace System.Text
m_ChunkLength = m_ChunkChars.Length;
}
- // Expand the builder to add another chunk.
+ // Expand the builder to add another chunk.
int restLength = valueCount - firstLength;
ExpandByABlock(restLength);
Debug.Assert(m_ChunkLength == 0, "A new block was not created.");
@@ -1948,16 +2087,16 @@ namespace System.Text
{
fixed (char* valuePtr = value)
{
- // calculate the total amount of extra space or space needed for all the replacements.
+ // calculate the total amount of extra space or space needed for all the replacements.
int delta = (value.Length - removeCount) * replacementsCount;
StringBuilder targetChunk = sourceChunk; // the target as we copy chars down
int targetIndexInChunk = replacements[0];
- // Make the room needed for all the new characters if needed.
+ // Make the room needed for all the new characters if needed.
if (delta > 0)
MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true);
- // We made certain that characters after the insertion point are not moved,
+ // We made certain that characters after the insertion point are not moved,
int i = 0;
for (;;)
{
@@ -1974,7 +2113,7 @@ namespace System.Text
Debug.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen");
Debug.Assert(gapStart <= gapEnd, "negative gap size");
Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big");
- if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
+ if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
{
// Copy the gap data between the current replacement and the next replacement
fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart])
@@ -1987,7 +2126,7 @@ namespace System.Text
}
}
- // Remove extra space if necessary.
+ // Remove extra space if necessary.
if (delta < 0)
Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk);
}
@@ -2044,7 +2183,7 @@ namespace System.Text
/// </param>
/// <param name="value">The pointer to the start of the character buffer.</param>
/// <param name="count">The number of characters in the buffer.</param>
- unsafe private void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
+ private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
{
if (count != 0)
{
@@ -2056,7 +2195,7 @@ namespace System.Text
int lengthToCopy = Math.Min(lengthInChunk, count);
ThreadSafeCopy(value, chunk.m_ChunkChars, indexInChunk, lengthToCopy);
- // Advance the index.
+ // Advance the index.
indexInChunk += lengthToCopy;
if (indexInChunk >= chunk.m_ChunkLength)
{
@@ -2374,7 +2513,7 @@ namespace System.Text
int endIndex = startIndex + count;
- // Find the chunks for the start and end of the block to delete.
+ // Find the chunks for the start and end of the block to delete.
chunk = this;
StringBuilder endChunk = null;
int endIndexInChunk = 0;
@@ -2425,7 +2564,7 @@ namespace System.Text
// SafeCritical: We ensure that `endIndexInChunk + copyCount` is within range of `m_ChunkChars`, and
// also ensure that `copyTargetIndexInChunk + copyCount` is within the chunk.
- // Remove any characters in the end chunk, by sliding the characters down.
+ // Remove any characters in the end chunk, by sliding the characters down.
if (copyTargetIndexInChunk != endIndexInChunk) // Sometimes no move is necessary
{
ThreadSafeCopy(endChunk.m_ChunkChars, endIndexInChunk, endChunk.m_ChunkChars, copyTargetIndexInChunk, copyCount);
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs
new file mode 100644
index 000000000..e699cc27c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs
@@ -0,0 +1,62 @@
+// 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.
+
+namespace System.Text
+{
+ /// <summary>Provide a cached reusable instance of stringbuilder per thread.</summary>
+ internal static class StringBuilderCache
+ {
+ // The value 360 was chosen in discussion with performance experts as a compromise between using
+ // as litle memory per thread as possible and still covering a large part of short-lived
+ // StringBuilder creations on the startup path of VS designers.
+ private const int MaxBuilderSize = 360;
+ private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
+
+ // WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
+ // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
+ // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
+ // Get in touch with the diagnostics team if you have questions.
+ [ThreadStatic]
+ private static StringBuilder t_cachedInstance;
+
+ /// <summary>Get a StringBuilder for the specified capacity.</summary>
+ /// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
+ public static StringBuilder Acquire(int capacity = DefaultCapacity)
+ {
+ if (capacity <= MaxBuilderSize)
+ {
+ StringBuilder sb = t_cachedInstance;
+ if (sb != null)
+ {
+ // Avoid stringbuilder block fragmentation by getting a new StringBuilder
+ // when the requested size is larger than the current capacity
+ if (capacity <= sb.Capacity)
+ {
+ t_cachedInstance = null;
+ sb.Clear();
+ return sb;
+ }
+ }
+ }
+ return new StringBuilder(capacity);
+ }
+
+ /// <summary>Place the specified builder in the cache if it is not too big.</summary>
+ public static void Release(StringBuilder sb)
+ {
+ if (sb.Capacity <= MaxBuilderSize)
+ {
+ t_cachedInstance = sb;
+ }
+ }
+
+ /// <summary>ToString() the stringbuilder, Release it to the cache, and return the resulting string.</summary>
+ public static string GetStringAndRelease(StringBuilder sb)
+ {
+ string result = sb.ToString();
+ Release(sb);
+ return result;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
index 7828775ea..86169e6b1 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
@@ -103,13 +103,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -125,11 +125,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -144,10 +144,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -158,20 +158,20 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -198,16 +198,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -230,10 +230,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -250,13 +250,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -276,10 +276,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -294,16 +294,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -326,10 +326,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -342,23 +342,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -417,7 +417,7 @@ namespace System.Text
//
// In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
//
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// They're all legal
highSurrogate = '\0';
@@ -447,7 +447,7 @@ namespace System.Text
}
// Do we have another high surrogate?
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
//
// We'll have a high surrogate to check next time.
@@ -457,7 +457,7 @@ namespace System.Text
}
// Check for illegal characters
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// We have a leading low surrogate, do the fallback
charsForFallback = chars;
@@ -552,7 +552,7 @@ namespace System.Text
//
// In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
//
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// Is it a legal one?
uint iTemp = GetSurrogate(highSurrogate, ch);
@@ -616,7 +616,7 @@ namespace System.Text
}
// Do we have another high surrogate?, if so remember it
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
//
// We'll have a high surrogate to check next time.
@@ -626,7 +626,7 @@ namespace System.Text
}
// Check for illegal characters (low surrogate)
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// We have a leading low surrogate, do the fallback
charsForFallback = chars;
@@ -1159,7 +1159,7 @@ namespace System.Text
_emitUTF32ByteOrderMark ? (_bigEndian ? s_bigEndianPreamble : s_littleEndianPreamble) :
Array.Empty<byte>();
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF32Encoding that = value as UTF32Encoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
index 0246c2891..5c51c8107 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
@@ -14,17 +14,17 @@ namespace System.Text
{
public class UTF7Encoding : Encoding
{
- private const String base64Chars =
+ private const string base64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 0123456789111111111122222222223333333333444444444455555555556666
// 012345678901234567890123456789012345678901234567890123
// These are the characters that can be directly encoded in UTF7.
- private const String directChars =
+ private const string directChars =
"\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
// These are the characters that can be optionally directly encoded in UTF7.
- private const String optionalChars =
+ private const string optionalChars =
"!\"#$%&*;<=>@[]^_`{|}";
// Used by Encoding.UTF7 for lazy initialization
@@ -88,16 +88,16 @@ namespace System.Text
}
// We go ahead and set this because Encoding expects it, however nothing can fall back in UTF7.
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// UTF7 had an odd decoderFallback behavior, and the Encoder fallback
// is irrelevant because we encode surrogates individually and never check for unmatched ones
// (so nothing can fallback during encoding)
- this.encoderFallback = new EncoderReplacementFallback(String.Empty);
+ this.encoderFallback = new EncoderReplacementFallback(string.Empty);
this.decoderFallback = new DecoderUTF7Fallback();
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF7Encoding that = value as UTF7Encoding;
if (that != null)
@@ -133,13 +133,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -159,7 +159,7 @@ namespace System.Text
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -174,10 +174,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -192,16 +192,16 @@ namespace System.Text
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -228,16 +228,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -260,10 +260,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -280,13 +280,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -306,10 +306,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -324,16 +324,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -356,10 +356,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -372,23 +372,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -396,7 +396,7 @@ namespace System.Text
// End of standard methods copied from EncodingNLS.cs
//
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
{
Debug.Assert(chars != null, "[UTF7Encoding.GetByteCount]chars!=null");
Debug.Assert(count >= 0, "[UTF7Encoding.GetByteCount]count >=0");
@@ -405,8 +405,8 @@ namespace System.Text
return GetBytes(chars, count, null, 0, baseEncoder);
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
{
Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetBytes]byteCount >=0");
Debug.Assert(chars != null, "[UTF7Encoding.GetBytes]chars!=null");
@@ -545,7 +545,7 @@ namespace System.Text
return buffer.Count;
}
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(count >= 0, "[UTF7Encoding.GetCharCount]count >=0");
Debug.Assert(bytes != null, "[UTF7Encoding.GetCharCount]bytes!=null");
@@ -554,8 +554,8 @@ namespace System.Text
return GetChars(bytes, count, null, 0, baseDecoder);
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetChars]byteCount >=0");
Debug.Assert(bytes != null, "[UTF7Encoding.GetChars]bytes!=null");
@@ -873,7 +873,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderUTF7Fallback that = value as DecoderUTF7Fallback;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
index 67f87c9b0..c9e51f661 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
@@ -93,7 +93,7 @@ namespace System.Text
SetDefaultFallbacks();
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For UTF-X encodings, we use a replacement fallback with an empty string
if (_isThrowException)
@@ -130,13 +130,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -152,7 +152,7 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String chars)
+ public override unsafe int GetByteCount(string chars)
{
// Validate input
if (chars==null)
@@ -171,34 +171,42 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
+ public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetByteCount(charsPtr, chars.Length, baseEncoder: null);
+ }
+ }
+
// Parent method is safe.
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -225,16 +233,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -257,14 +265,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
+ public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, baseEncoder: null);
+ }
+ }
+
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
//
@@ -277,13 +294,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -303,14 +320,22 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
+ public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetCharCount(bytesPtr, bytes.Length, baseDecoder: null);
+ }
+ }
+
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
@@ -321,16 +346,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -353,14 +378,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
+ public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, baseDecoder: null);
+ }
+ }
+
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
//
@@ -369,23 +403,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -395,7 +429,7 @@ namespace System.Text
// To simplify maintenance, the structure of GetByteCount and GetBytes should be
// kept the same as much as possible
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
{
// For fallback we may need a fallback buffer.
// We wait to initialize it though in case we don't have any broken input unicode
@@ -715,12 +749,15 @@ namespace System.Text
break;
LongCodeWithMask:
-#if BIGENDIAN
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
-#else // BIGENDIAN
- ch = (char)ch;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch = (char)ch;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
pSrc++;
if (ch <= 0x7F)
@@ -783,13 +820,13 @@ namespace System.Text
// diffs two char pointers using unsigned arithmetic. The unsigned arithmetic
// is good enough for us, and it tends to generate better code than the signed
// arithmetic generated by default
- unsafe private static int PtrDiff(char* a, char* b)
+ private static unsafe int PtrDiff(char* a, char* b)
{
return (int)(((uint)((byte*)a - (byte*)b)) >> 1);
}
// byte* flavor just for parity
- unsafe private static int PtrDiff(byte* a, byte* b)
+ private static unsafe int PtrDiff(byte* a, byte* b)
{
return (int)(a - b);
}
@@ -801,8 +838,8 @@ namespace System.Text
// Our workhorse
// Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
{
Debug.Assert(chars != null, "[UTF8Encoding.GetBytes]chars!=null");
Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetBytes]byteCount >=0");
@@ -1142,31 +1179,37 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (byte)(ch>>16);
- *(pTarget+1) = (byte)ch;
- pSrc += 4;
- *(pTarget+2) = (byte)(chc>>16);
- *(pTarget+3) = (byte)chc;
- pTarget += 4;
-#else // BIGENDIAN
- *pTarget = (byte)ch;
- *(pTarget + 1) = (byte)(ch >> 16);
- pSrc += 4;
- *(pTarget + 2) = (byte)chc;
- *(pTarget + 3) = (byte)(chc >> 16);
- pTarget += 4;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (byte)ch;
+ *(pTarget + 1) = (byte)(ch >> 16);
+ pSrc += 4;
+ *(pTarget + 2) = (byte)chc;
+ *(pTarget + 3) = (byte)(chc >> 16);
+ pTarget += 4;
+ }
+ else
+ {
+ *pTarget = (byte)(ch>>16);
+ *(pTarget+1) = (byte)ch;
+ pSrc += 4;
+ *(pTarget+2) = (byte)(chc>>16);
+ *(pTarget+3) = (byte)chc;
+ pTarget += 4;
+ }
}
continue;
LongCodeWithMask:
-#if BIGENDIAN
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
-#else // BIGENDIAN
- ch = (char)ch;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch = (char)ch;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
pSrc++;
if (ch > 0x7F)
@@ -1284,7 +1327,7 @@ namespace System.Text
//
// To simplify maintenance, the structure of GetCharCount and GetChars should be
// kept the same as much as possible
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(count >= 0, "[UTF8Encoding.GetCharCount]count >=0");
Debug.Assert(bytes != null, "[UTF8Encoding.GetCharCount]bytes!=null");
@@ -1564,17 +1607,26 @@ namespace System.Text
}
break;
-#if BIGENDIAN
- LongCodeWithMask32:
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
- LongCodeWithMask16:
- ch = (int)(((uint)ch) >> 8);
-#else // BIGENDIAN
LongCodeWithMask32:
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
LongCodeWithMask16:
- ch &= 0xFF;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ ch = (int)(((uint)ch) >> 8);
+ }
+
pSrc++;
if (ch <= 0x7F)
{
@@ -1713,8 +1765,8 @@ namespace System.Text
//
// To simplify maintenance, the structure of GetCharCount and GetChars should be
// kept the same as much as possible
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(chars != null, "[UTF8Encoding.GetChars]chars!=null");
Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetChars]count >=0");
@@ -2048,17 +2100,20 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (char)((ch >> 8) & 0x7F);
- pSrc += 2;
- *(pTarget+1) = (char)(ch & 0x7F);
- pTarget += 2;
-#else // BIGENDIAN
- *pTarget = (char)(ch & 0x7F);
- pSrc += 2;
- *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
- pTarget += 2;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (char)(ch & 0x7F);
+ pSrc += 2;
+ *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
+ pTarget += 2;
+ }
+ else
+ {
+ *pTarget = (char)((ch >> 8) & 0x7F);
+ pSrc += 2;
+ *(pTarget+1) = (char)(ch & 0x7F);
+ pTarget += 2;
+ }
}
// Run 8 characters at a time!
@@ -2072,43 +2127,54 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (char)((ch >> 24) & 0x7F);
- *(pTarget+1) = (char)((ch >> 16) & 0x7F);
- *(pTarget+2) = (char)((ch >> 8) & 0x7F);
- *(pTarget+3) = (char)(ch & 0x7F);
- pSrc += 8;
- *(pTarget+4) = (char)((chb >> 24) & 0x7F);
- *(pTarget+5) = (char)((chb >> 16) & 0x7F);
- *(pTarget+6) = (char)((chb >> 8) & 0x7F);
- *(pTarget+7) = (char)(chb & 0x7F);
- pTarget += 8;
-#else // BIGENDIAN
- *pTarget = (char)(ch & 0x7F);
- *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
- *(pTarget + 2) = (char)((ch >> 16) & 0x7F);
- *(pTarget + 3) = (char)((ch >> 24) & 0x7F);
- pSrc += 8;
- *(pTarget + 4) = (char)(chb & 0x7F);
- *(pTarget + 5) = (char)((chb >> 8) & 0x7F);
- *(pTarget + 6) = (char)((chb >> 16) & 0x7F);
- *(pTarget + 7) = (char)((chb >> 24) & 0x7F);
- pTarget += 8;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (char)(ch & 0x7F);
+ *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
+ *(pTarget + 2) = (char)((ch >> 16) & 0x7F);
+ *(pTarget + 3) = (char)((ch >> 24) & 0x7F);
+ pSrc += 8;
+ *(pTarget + 4) = (char)(chb & 0x7F);
+ *(pTarget + 5) = (char)((chb >> 8) & 0x7F);
+ *(pTarget + 6) = (char)((chb >> 16) & 0x7F);
+ *(pTarget + 7) = (char)((chb >> 24) & 0x7F);
+ pTarget += 8;
+ }
+ else
+ {
+ *pTarget = (char)((ch >> 24) & 0x7F);
+ *(pTarget+1) = (char)((ch >> 16) & 0x7F);
+ *(pTarget+2) = (char)((ch >> 8) & 0x7F);
+ *(pTarget+3) = (char)(ch & 0x7F);
+ pSrc += 8;
+ *(pTarget+4) = (char)((chb >> 24) & 0x7F);
+ *(pTarget+5) = (char)((chb >> 16) & 0x7F);
+ *(pTarget+6) = (char)((chb >> 8) & 0x7F);
+ *(pTarget+7) = (char)(chb & 0x7F);
+ pTarget += 8;
+ }
}
break;
-#if BIGENDIAN
- LongCodeWithMask32:
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
- LongCodeWithMask16:
- ch = (int)(((uint)ch) >> 8);
-#else // BIGENDIAN
LongCodeWithMask32:
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
LongCodeWithMask16:
- ch &= 0xFF;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ ch = (int)(((uint)ch) >> 8);
+ }
pSrc++;
if (ch <= 0x7F)
{
@@ -2173,7 +2239,7 @@ namespace System.Text
// extra byte, we're already planning 2 chars for 2 of these bytes,
// but the big loop is testing the target against pStop, so we need
- // to subtract 2 more or we risk overrunning the input. Subtract
+ // to subtract 2 more or we risk overrunning the input. Subtract
// one here and one below.
pStop--;
}
@@ -2323,11 +2389,17 @@ namespace System.Text
private unsafe int FallbackInvalidByteSequence(
byte* pSrc, int ch, DecoderFallbackBuffer fallback)
{
+ // Calling GetBytesUnknown can adjust the pSrc pointer but we need to pass the pointer before the adjustment
+ // to fallback.InternalFallback. The input pSrc to fallback.InternalFallback will only be used to calculate the
+ // index inside bytesUnknown and if we pass the adjusted pointer we can end up with negative index values.
+ // We store the original pSrc in pOriginalSrc and then pass pOriginalSrc to fallback.InternalFallback.
+ byte* pOriginalSrc = pSrc;
+
// Get our byte[]
byte[] bytesUnknown = GetBytesUnknown(ref pSrc, ch);
// Do the actual fallback
- int count = fallback.InternalFallback(bytesUnknown, pSrc);
+ int count = fallback.InternalFallback(bytesUnknown, pOriginalSrc);
// # of fallback chars expected.
// Note that we only get here for "long" sequences, and have already unreserved
@@ -2336,7 +2408,7 @@ namespace System.Text
}
// Note that some of these bytes may have come from a previous fallback, so we cannot
- // just decrement the pointer and use the values we read. In those cases we have
+ // just decrement the pointer and use the values we read. In those cases we have
// to regenerate the original values.
private unsafe byte[] GetBytesUnknown(ref byte* pSrc, int ch)
{
@@ -2481,7 +2553,7 @@ namespace System.Text
_emitUTF8Identifier ? s_preamble :
Array.Empty<byte>();
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF8Encoding that = value as UTF8Encoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
index 342bf53d6..6a27d2c85 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
@@ -6,11 +6,17 @@
// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
//
+// This define can be used to turn off the fast loops. Useful for finding whether
+// the problem is fastloop-specific.
+#define FASTLOOP
+
using System;
using System.Globalization;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
namespace System.Text
{
public class UnicodeEncoding : Encoding
@@ -23,15 +29,14 @@ namespace System.Text
private static readonly byte[] s_bigEndianPreamble = new byte[2] { 0xfe, 0xff };
private static readonly byte[] s_littleEndianPreamble = new byte[2] { 0xff, 0xfe };
- internal bool isThrowException = false;
+ private bool isThrowException = false;
- internal bool bigEndian = false;
- internal bool byteOrderMark = true;
+ private bool bigEndian = false;
+ private bool byteOrderMark = true;
// Unicode version 2.0 character size in bytes
public const int CharSize = 2;
-
public UnicodeEncoding()
: this(false, true)
{
@@ -56,7 +61,7 @@ namespace System.Text
SetDefaultFallbacks();
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For UTF-X encodings, we use a replacement fallback with an empty string
if (this.isThrowException)
@@ -89,13 +94,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -111,11 +116,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -130,10 +135,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -144,20 +149,20 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -184,16 +189,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -216,10 +221,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -236,13 +241,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -262,10 +267,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -280,16 +285,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -312,10 +317,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -332,19 +337,19 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -352,7 +357,7 @@ namespace System.Text
// End of standard methods copied from EncodingNLS.cs
//
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetByteCount]chars!=null");
Debug.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0");
@@ -372,11 +377,6 @@ namespace System.Text
bool wasHereBefore = false;
- // Need -1 to check 2 at a time. If we have an even #, longChars will go
- // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
- // will go from longEnd - 1 long to longEnd. (Might not get to use this)
- ulong* longEnd = (ulong*)(charEnd - 3);
-
// For fallback we may need a fallback buffer
EncoderFallbackBuffer fallbackBuffer = null;
char* charsForFallback;
@@ -410,19 +410,21 @@ namespace System.Text
if (ch == 0)
{
// No fallback, maybe we can do it fast
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
- if ( bigEndian &&
-#else
- if (!bigEndian &&
-#endif // BIGENDIAN
-
-#if BIT64 // 64 bit CPU needs to be long aligned for this to work.
- charLeftOver == 0 && (unchecked((long)chars) & 7) == 0)
+#if FASTLOOP
+ // If endianess is backwards then each pair of bytes would be backwards.
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- charLeftOver == 0 && (unchecked((int)chars) & 3) == 0)
+ (unchecked((int)chars) & 3) == 0 &&
#endif
+ charLeftOver == 0)
{
+ // Need -1 to check 2 at a time. If we have an even #, longChars will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(charEnd - 3);
+
// Need new char* so we can check 4 at a time
ulong* longChars = (ulong*)chars;
@@ -453,11 +455,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longChars) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -480,7 +479,7 @@ namespace System.Text
if (chars >= charEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// No fallback, just get next char
ch = *chars;
@@ -651,8 +650,8 @@ namespace System.Text
return byteCount;
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetBytes]chars!=null");
Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetBytes]byteCount >=0");
@@ -700,17 +699,14 @@ namespace System.Text
if (ch == 0)
{
// No fallback, maybe we can do it fast
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
- if ( bigEndian &&
-#else
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // 64 bit CPU needs to be long aligned for this to work, 32 bit CPU needs to be 32 bit aligned
- (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#if FASTLOOP
+ // If endianess is backwards then each pair of bytes would be backwards.
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
-#endif // BIT64
+ (unchecked((int)chars) & 3) == 0 &&
+#endif
charLeftOver == 0)
{
// Need -1 to check 2 at a time. If we have an even #, longChars will go
@@ -752,11 +748,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longChars) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -771,7 +764,7 @@ namespace System.Text
// else all < 0x8000 so we can use them
// We can use these 4 chars.
- *longBytes = *longChars;
+ Unsafe.WriteUnaligned<ulong>(longBytes, *longChars);
longChars++;
longBytes++;
}
@@ -782,66 +775,7 @@ namespace System.Text
if (chars >= charEnd)
break;
}
- // Not aligned, but maybe we can still be somewhat faster
- // Also somehow this optimizes the above loop? It seems to cause something above
- // to get enregistered, but I haven't figured out how to make that happen without this loop.
- else if ((charLeftOver == 0) &&
-#if BIGENDIAN
- bigEndian &&
-#else
- !bigEndian &&
-#endif // BIGENDIAN
-
-#if BIT64
- (unchecked((long)chars) & 7) != (unchecked((long)bytes) & 7) && // Only do this if chars & bytes are out of line, otherwise faster loop will be faster next time
-#else
- (unchecked((int)chars) & 3) != (unchecked((int)bytes) & 3) && // Only do this if chars & bytes are out of line, otherwise faster loop will be faster next time
-#endif // BIT64
- (unchecked((int)(bytes)) & 1) == 0)
- {
- // # to use
- long iCount = ((byteEnd - bytes) >> 1 < charEnd - chars) ?
- (byteEnd - bytes) >> 1 : charEnd - chars;
-
- // Need new char*
- char* charOut = ((char*)bytes); // a char* for our output
- char* tempEnd = chars + iCount - 1; // Our end pointer
-
- while (chars < tempEnd)
- {
- if (*chars >= (char)0xd800 && *chars <= (char)0xdfff)
- {
- // break for fallback for low surrogate
- if (*chars >= 0xdc00)
- break;
-
- // break if next one's not a low surrogate (will do fallback)
- if (*(chars + 1) < 0xdc00 || *(chars + 1) > 0xdfff)
- break;
-
- // They both exist, use them
- }
- // If 2nd char is surrogate & this one isn't then only add one
- else if (*(chars + 1) >= (char)0xd800 && *(chars + 1) <= 0xdfff)
- {
- *charOut = *chars;
- charOut++;
- chars++;
- continue;
- }
-
- *charOut = *chars;
- *(charOut + 1) = *(chars + 1);
- charOut += 2;
- chars += 2;
- }
-
- bytes = (byte*)charOut;
-
- if (chars >= charEnd)
- break;
- }
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// No fallback, just get next char
ch = *chars;
@@ -1070,13 +1004,10 @@ namespace System.Text
encoder == null || !encoder._throwOnOverflow,
"[UnicodeEncoding.GetBytes]Expected empty fallback buffer if not converting");
- // We used to copy it fast, but this doesn't check for surrogates
- // System.IO.__UnmanagedMemoryStream.memcpyimpl(bytes, (byte*)chars, usedByteCount);
-
return (int)(bytes - byteStart);
}
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(bytes != null, "[UnicodeEncoding.GetCharCount]bytes!=null");
Debug.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0");
@@ -1093,11 +1024,6 @@ namespace System.Text
// Start by assuming same # of chars as bytes
int charCount = count >> 1;
- // Need -1 to check 2 at a time. If we have an even #, longBytes will go
- // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
- // will go from longEnd - 1 long to longEnd. (Might not get to use this)
- ulong* longEnd = (ulong*)(byteEnd - 7);
-
// For fallback we may need a fallback buffer
DecoderFallbackBuffer fallbackBuffer = null;
@@ -1126,19 +1052,20 @@ namespace System.Text
{
// If we're aligned then maybe we can do it fast
// That'll hurt if we're unaligned because we'll always test but never be aligned
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN
- if (bigEndian &&
-#else // BIGENDIAN
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // win64 has to be long aligned
+#if FASTLOOP
+ if ((bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
(unchecked((long)bytes) & 7) == 0 &&
#else
(unchecked((int)bytes) & 3) == 0 &&
#endif // BIT64
lastByte == -1 && lastChar == 0)
{
+ // Need -1 to check 2 at a time. If we have an even #, longBytes will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(byteEnd - 7);
+
// Need new char* so we can check 4 at a time
ulong* longBytes = (ulong*)bytes;
@@ -1169,11 +1096,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longBytes) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -1196,7 +1120,7 @@ namespace System.Text
if (bytes >= byteEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// Get 1st byte
if (lastByte < 0)
@@ -1410,8 +1334,8 @@ namespace System.Text
return charCount;
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetChars]chars!=null");
Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetChars]byteCount >=0");
@@ -1449,17 +1373,13 @@ namespace System.Text
{
// If we're aligned then maybe we can do it fast
// That'll hurt if we're unaligned because we'll always test but never be aligned
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN
- if (bigEndian &&
-#else // BIGENDIAN
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // win64 has to be long aligned
- (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#if FASTLOOP
+ if ((bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
-#endif // BIT64
+ (unchecked((int)chars) & 3) == 0 &&
+#endif
lastByte == -1 && lastChar == 0)
{
// Need -1 to check 2 at a time. If we have an even #, longChars will go
@@ -1501,11 +1421,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longBytes) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -1520,7 +1437,7 @@ namespace System.Text
// else all < 0x8000 so we can use them
// We can use these 4 chars.
- *longChars = *longBytes;
+ Unsafe.WriteUnaligned<ulong>(longChars, *longBytes);
longBytes++;
longChars++;
}
@@ -1531,7 +1448,7 @@ namespace System.Text
if (bytes >= byteEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// Get 1st byte
if (lastByte < 0)
@@ -1840,9 +1757,6 @@ namespace System.Text
decoder.lastByte = lastByte;
}
- // Used to do this the old way
- // System.IO.__UnmanagedMemoryStream.memcpyimpl((byte*)chars, bytes, byteCount);
-
// Shouldn't have anything in fallback buffer for GetChars
// (don't have to check _throwOnOverflow for count or chars)
Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
@@ -1875,7 +1789,7 @@ namespace System.Text
else
return new byte[2] { 0xff, 0xfe };
}
- return Array.Empty<Byte>();
+ return Array.Empty<byte>();
}
public override ReadOnlySpan<byte> Preamble =>
@@ -1928,7 +1842,7 @@ namespace System.Text
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UnicodeEncoding that = value as UnicodeEncoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
index 18d564867..74b5dacf9 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
namespace System.Text
{
- internal ref struct ValueStringBuilder
+ internal ref partial struct ValueStringBuilder
{
private char[] _arrayToReturnToPool;
private Span<char> _chars;
@@ -22,11 +22,19 @@ namespace System.Text
_pos = 0;
}
+ public ValueStringBuilder(int initialCapacity)
+ {
+ _arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialCapacity);
+ _chars = _arrayToReturnToPool;
+ _pos = 0;
+ }
+
public int Length
{
get => _pos;
set
{
+ Debug.Assert(value >= 0);
Debug.Assert(value <= _chars.Length);
_pos = value;
}
@@ -40,7 +48,30 @@ namespace System.Text
Grow(capacity - _chars.Length);
}
- public ref char GetPinnableReference() => ref MemoryMarshal.GetReference(_chars);
+ /// <summary>
+ /// Get a pinnable reference to the builder.
+ /// Does not ensure there is a null char after <see cref="Length"/>
+ /// This overload is pattern matched in the C# 7.3+ compiler so you can omit
+ /// the explicit method call, and write eg "fixed (char* c = builder)"
+ /// </summary>
+ public ref char GetPinnableReference()
+ {
+ return ref MemoryMarshal.GetReference(_chars);
+ }
+
+ /// <summary>
+ /// Get a pinnable reference to the builder.
+ /// </summary>
+ /// <param name="terminate">Ensures that the builder has a null char after <see cref="Length"/></param>
+ public ref char GetPinnableReference(bool terminate)
+ {
+ if (terminate)
+ {
+ EnsureCapacity(Length + 1);
+ _chars[Length] = '\0';
+ }
+ return ref MemoryMarshal.GetReference(_chars);
+ }
public ref char this[int index]
{
@@ -53,12 +84,31 @@ namespace System.Text
public override string ToString()
{
- var s = new string(_chars.Slice(0, _pos));
+ var s = _chars.Slice(0, _pos).ToString();
Dispose();
return s;
}
+ /// <summary>Returns the underlying storage of the builder.</summary>
+ public Span<char> RawChars => _chars;
+
+ /// <summary>
+ /// Returns a span around the contents of the builder.
+ /// </summary>
+ /// <param name="terminate">Ensures that the builder has a null char after <see cref="Length"/></param>
+ public ReadOnlySpan<char> AsSpan(bool terminate)
+ {
+ if (terminate)
+ {
+ EnsureCapacity(Length + 1);
+ _chars[Length] = '\0';
+ }
+ return _chars.Slice(0, _pos);
+ }
+
public ReadOnlySpan<char> AsSpan() => _chars.Slice(0, _pos);
+ public ReadOnlySpan<char> AsSpan(int start) => _chars.Slice(start, _pos - start);
+ public ReadOnlySpan<char> AsSpan(int start, int length) => _chars.Slice(start, length);
public bool TryCopyTo(Span<char> destination, out int charsWritten)
{
@@ -93,7 +143,7 @@ namespace System.Text
public void Append(char c)
{
int pos = _pos;
- if (pos < _chars.Length)
+ if ((uint)pos < (uint)_chars.Length)
{
_chars[pos] = c;
_pos = pos + 1;
@@ -108,7 +158,7 @@ namespace System.Text
public void Append(string s)
{
int pos = _pos;
- if (s.Length == 1 && pos < _chars.Length) // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
+ if (s.Length == 1 && (uint)pos < (uint)_chars.Length) // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
{
_chars[pos] = s[0];
_pos = pos + 1;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs b/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs
index c7e604f33..bd504dd27 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs
@@ -27,13 +27,13 @@ namespace System.Threading
HResult = HResults.COR_E_ABANDONEDMUTEX;
}
- public AbandonedMutexException(String message)
+ public AbandonedMutexException(string message)
: base(message)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
}
- public AbandonedMutexException(String message, Exception inner)
+ public AbandonedMutexException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
@@ -46,14 +46,14 @@ namespace System.Threading
SetupException(location, handle);
}
- public AbandonedMutexException(String message, int location, WaitHandle handle)
+ public AbandonedMutexException(string message, int location, WaitHandle handle)
: base(message)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
SetupException(location, handle);
}
- public AbandonedMutexException(String message, Exception inner, int location, WaitHandle handle)
+ public AbandonedMutexException(string message, Exception inner, int location, WaitHandle handle)
: base(message, inner)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs b/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs
index 3531265be..12d650243 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs
@@ -61,7 +61,7 @@ namespace System.Threading
get
{
object obj = ExecutionContext.GetLocalValue(this);
- return (obj == null) ? default(T) : (T)obj;
+ return (obj == null) ? default : (T)obj;
}
set
{
@@ -72,8 +72,8 @@ namespace System.Threading
void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged)
{
Debug.Assert(m_valueChangedHandler != null);
- T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj;
- T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj;
+ T previousValue = previousValueObj == null ? default : (T)previousValueObj;
+ T currentValue = currentValueObj == null ? default : (T)currentValueObj;
m_valueChangedHandler(new AsyncLocalValueChangedArgs<T>(previousValue, currentValue, contextChanged));
}
}
@@ -86,19 +86,18 @@ namespace System.Threading
void OnValueChanged(object previousValue, object currentValue, bool contextChanged);
}
- public struct AsyncLocalValueChangedArgs<T>
+ public readonly struct AsyncLocalValueChangedArgs<T>
{
- public T PreviousValue { get; private set; }
- public T CurrentValue { get; private set; }
+ public T PreviousValue { get; }
+ public T CurrentValue { get; }
//
// If the value changed because we changed to a different ExecutionContext, this is true. If it changed
// because someone set the Value property, this is false.
//
- public bool ThreadContextChanged { get; private set; }
+ public bool ThreadContextChanged { get; }
internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged)
- : this()
{
PreviousValue = previousValue;
CurrentValue = currentValue;
@@ -114,7 +113,7 @@ namespace System.Threading
internal interface IAsyncLocalValueMap
{
bool TryGetValue(IAsyncLocal key, out object value);
- IAsyncLocalValueMap Set(IAsyncLocal key, object value);
+ IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent);
}
//
@@ -124,14 +123,31 @@ namespace System.Threading
{
public static IAsyncLocalValueMap Empty { get; } = new EmptyAsyncLocalValueMap();
+ public static bool IsEmpty(IAsyncLocalValueMap asyncLocalValueMap)
+ {
+ Debug.Assert(asyncLocalValueMap != null);
+ Debug.Assert(asyncLocalValueMap == Empty || asyncLocalValueMap.GetType() != typeof(EmptyAsyncLocalValueMap));
+
+ return asyncLocalValueMap == Empty;
+ }
+
+ public static IAsyncLocalValueMap Create(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
+ {
+ // If the value isn't null or a null value may not be treated as nonexistent, then create a new one-element map
+ // to store the key/value pair. Otherwise, use the empty map.
+ return value != null || !treatNullValueAsNonexistent ?
+ new OneElementAsyncLocalValueMap(key, value) :
+ Empty;
+ }
+
// Instance without any key/value pairs. Used as a singleton/
- internal sealed class EmptyAsyncLocalValueMap : IAsyncLocalValueMap
+ private sealed class EmptyAsyncLocalValueMap : IAsyncLocalValueMap
{
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- // If the value isn't null, then create a new one-element map to store
- // the key/value pair. If it is null, then we're still empty.
- return value != null ?
+ // If the value isn't null or a null value may not be treated as nonexistent, then create a new one-element map
+ // to store the key/value pair. Otherwise, use the empty map.
+ return value != null || !treatNullValueAsNonexistent ?
new OneElementAsyncLocalValueMap(key, value) :
(IAsyncLocalValueMap)this;
}
@@ -144,7 +160,7 @@ namespace System.Threading
}
// Instance with one key/value pair.
- internal sealed class OneElementAsyncLocalValueMap : IAsyncLocalValueMap
+ private sealed class OneElementAsyncLocalValueMap : IAsyncLocalValueMap
{
private readonly IAsyncLocal _key1;
private readonly object _value1;
@@ -154,21 +170,20 @@ namespace System.Threading
_key1 = key; _value1 = value;
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
- // The value is non-null. If the key matches one already contained in this map,
- // then create a new one-element map with the updated value, otherwise create
- // a two-element map with the additional key/value.
+ // If the key matches one already contained in this map, then create a new one-element map with the updated
+ // value, otherwise create a two-element map with the additional key/value.
return ReferenceEquals(key, _key1) ?
new OneElementAsyncLocalValueMap(key, value) :
(IAsyncLocalValueMap)new TwoElementAsyncLocalValueMap(_key1, _value1, key, value);
}
else
{
- // The value is null. If the key exists in this map, remove it by downgrading to an empty map.
- // Otherwise, there's nothing to add or remove, so just return this map.
+ // If the key exists in this map, remove it by downgrading to an empty map. Otherwise, there's nothing to
+ // add or remove, so just return this map.
return ReferenceEquals(key, _key1) ?
Empty :
(IAsyncLocalValueMap)this;
@@ -202,13 +217,12 @@ namespace System.Threading
_key2 = key2; _value2 = value2;
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
- // The value is non-null. If the key matches one already contained in this map,
- // then create a new two-element map with the updated value, otherwise create
- // a three-element map with the additional key/value.
+ // If the key matches one already contained in this map, then create a new two-element map with the updated
+ // value, otherwise create a three-element map with the additional key/value.
return
ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(key, value, _key2, _value2) :
ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, key, value) :
@@ -216,8 +230,8 @@ namespace System.Threading
}
else
{
- // The value is null. If the key exists in this map, remove it by downgrading to a one-element map
- // without the key. Otherwise, there's nothing to add or remove, so just return this map.
+ // If the key exists in this map, remove it by downgrading to a one-element map without the key. Otherwise,
+ // there's nothing to add or remove, so just return this map.
return
ReferenceEquals(key, _key1) ? new OneElementAsyncLocalValueMap(_key2, _value2) :
ReferenceEquals(key, _key2) ? new OneElementAsyncLocalValueMap(_key1, _value1) :
@@ -258,12 +272,12 @@ namespace System.Threading
_key3 = key3; _value3 = value3;
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
- // The value is non-null. If the key matches one already contained in this map,
- // then create a new three-element map with the updated value.
+ // If the key matches one already contained in this map, then create a new three-element map with the
+ // updated value.
if (ReferenceEquals(key, _key1)) return new ThreeElementAsyncLocalValueMap(key, value, _key2, _value2, _key3, _value3);
if (ReferenceEquals(key, _key2)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, key, value, _key3, _value3);
if (ReferenceEquals(key, _key3)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value);
@@ -279,8 +293,8 @@ namespace System.Threading
}
else
{
- // The value is null. If the key exists in this map, remove it by downgrading to a two-element map
- // without the key. Otherwise, there's nothing to add or remove, so just return this map.
+ // If the key exists in this map, remove it by downgrading to a two-element map without the key. Otherwise,
+ // there's nothing to add or remove, so just return this map.
return
ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(_key2, _value2, _key3, _value3) :
ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, _key3, _value3) :
@@ -332,17 +346,18 @@ namespace System.Threading
_keyValues[index] = new KeyValuePair<IAsyncLocal, object>(key, value);
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
// Find the key in this map.
for (int i = 0; i < _keyValues.Length; i++)
{
if (ReferenceEquals(key, _keyValues[i].Key))
{
- // The key is in the map. If the value isn't null, then create a new map of the same
- // size that has all of the same pairs, with this new key/value pair overwriting the old.
- if (value != null)
+ // The key is in the map.
+ if (value != null || !treatNullValueAsNonexistent)
{
+ // Create a new map of the same size that has all of the same pairs, with this new key/value pair
+ // overwriting the old.
var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length);
Array.Copy(_keyValues, 0, multi._keyValues, 0, _keyValues.Length);
multi._keyValues[i] = new KeyValuePair<IAsyncLocal, object>(key, value);
@@ -350,8 +365,8 @@ namespace System.Threading
}
else if (_keyValues.Length == 4)
{
- // The value is null, and we only have four elements, one of which we're removing,
- // so downgrade to a three-element map, without the matching element.
+ // We only have four elements, one of which we're removing, so downgrade to a three-element map,
+ // without the matching element.
return
i == 0 ? new ThreeElementAsyncLocalValueMap(_keyValues[1].Key, _keyValues[1].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) :
i == 1 ? new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) :
@@ -360,8 +375,8 @@ namespace System.Threading
}
else
{
- // The value is null, and we have enough elements remaining to warrant a multi map.
- // Create a new one and copy all of the elements from this one, except the one to be removed.
+ // We have enough elements remaining to warrant a multi map. Create a new one and copy all of the
+ // elements from this one, except the one to be removed.
var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length - 1);
if (i != 0) Array.Copy(_keyValues, 0, multi._keyValues, 0, i);
if (i != _keyValues.Length - 1) Array.Copy(_keyValues, i + 1, multi._keyValues, i, _keyValues.Length - i - 1);
@@ -372,9 +387,9 @@ namespace System.Threading
// The key does not already exist in this map.
- // If the value is null, then we can simply return this same map, as there's nothing to add or remove.
- if (value == null)
+ if (value == null && treatNullValueAsNonexistent)
{
+ // We can simply return this same map, as there's nothing to add or remove.
return this;
}
@@ -418,14 +433,14 @@ namespace System.Threading
{
public ManyElementAsyncLocalValueMap(int capacity) : base(capacity) { }
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
int count = Count;
bool containsKey = ContainsKey(key);
// If the value being set exists, create a new many map, copy all of the elements from this one,
// and then store the new key/value pair into it. This is the most common case.
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
var map = new ManyElementAsyncLocalValueMap(count + (containsKey ? 0 : 1));
foreach (KeyValuePair<IAsyncLocal, object> pair in this)
@@ -436,15 +451,14 @@ namespace System.Threading
return map;
}
- // Otherwise, the value is null, which means null is being stored into an AsyncLocal.Value.
- // Since there's no observable difference at the API level between storing null and the key
- // not existing at all, we can downgrade to a smaller map rather than storing null.
+ // Otherwise, the value is null and a null value may be treated as nonexistent. We can downgrade to a smaller
+ // map rather than storing null.
// If the key is contained in this map, we're going to create a new map that's one pair smaller.
if (containsKey)
{
// If the new count would be within range of a multi map instead of a many map,
- // downgrade to the many map, which uses less memory and is faster to access.
+ // downgrade to the multi map, which uses less memory and is faster to access.
// Otherwise, just create a new many map that's missing this key.
if (count == MultiElementAsyncLocalValueMap.MaxMultiElements + 1)
{
@@ -475,8 +489,8 @@ namespace System.Threading
}
}
- // We were storing null, but the key wasn't in the map, so there's nothing to change.
- // Just return this instance.
+ // We were storing null and a null value may be treated as nonexistent, but the key wasn't in the map, so
+ // there's nothing to change. Just return this instance.
return this;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs b/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
new file mode 100644
index 000000000..68e6971a5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
@@ -0,0 +1,340 @@
+// 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.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Propagates notification that operations should be canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A <see cref="CancellationToken"/> may be created directly in an unchangeable canceled or non-canceled state
+ /// using the CancellationToken's constructors. However, to have a CancellationToken that can change
+ /// from a non-canceled to a canceled state,
+ /// <see cref="System.Threading.CancellationTokenSource">CancellationTokenSource</see> must be used.
+ /// CancellationTokenSource exposes the associated CancellationToken that may be canceled by the source through its
+ /// <see cref="System.Threading.CancellationTokenSource.Token">Token</see> property.
+ /// </para>
+ /// <para>
+ /// Once canceled, a token may not transition to a non-canceled state, and a token whose
+ /// <see cref="CanBeCanceled"/> is false will never change to one that can be canceled.
+ /// </para>
+ /// <para>
+ /// All members of this struct are thread-safe and may be used concurrently from multiple threads.
+ /// </para>
+ /// </remarks>
+ [DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")]
+ public readonly struct CancellationToken
+ {
+ // The backing TokenSource.
+ // if null, it implicitly represents the same thing as new CancellationToken(false).
+ // When required, it will be instantiated to reflect this.
+ private readonly CancellationTokenSource _source;
+ //!! warning. If more fields are added, the assumptions in CreateLinkedToken may no longer be valid
+
+ private readonly static Action<object> s_actionToActionObjShunt = obj => ((Action)obj)();
+
+ /// <summary>
+ /// Returns an empty CancellationToken value.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="CancellationToken"/> value returned by this property will be non-cancelable by default.
+ /// </remarks>
+ public static CancellationToken None => default;
+
+ /// <summary>
+ /// Gets whether cancellation has been requested for this token.
+ /// </summary>
+ /// <value>Whether cancellation has been requested for this token.</value>
+ /// <remarks>
+ /// <para>
+ /// This property indicates whether cancellation has been requested for this token,
+ /// either through the token initially being constructed in a canceled state, or through
+ /// calling <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see>
+ /// on the token's associated <see cref="CancellationTokenSource"/>.
+ /// </para>
+ /// <para>
+ /// If this property is true, it only guarantees that cancellation has been requested.
+ /// It does not guarantee that every registered handler
+ /// has finished executing, nor that cancellation requests have finished propagating
+ /// to all registered handlers. Additional synchronization may be required,
+ /// particularly in situations where related objects are being canceled concurrently.
+ /// </para>
+ /// </remarks>
+ public bool IsCancellationRequested => _source != null && _source.IsCancellationRequested;
+
+ /// <summary>
+ /// Gets whether this token is capable of being in the canceled state.
+ /// </summary>
+ /// <remarks>
+ /// If CanBeCanceled returns false, it is guaranteed that the token will never transition
+ /// into a canceled state, meaning that <see cref="IsCancellationRequested"/> will never
+ /// return true.
+ /// </remarks>
+ public bool CanBeCanceled => _source != null;
+
+ /// <summary>
+ /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is signaled when the token is canceled.</summary>
+ /// <remarks>
+ /// Accessing this property causes a <see cref="T:System.Threading.WaitHandle">WaitHandle</see>
+ /// to be instantiated. It is preferable to only use this property when necessary, and to then
+ /// dispose the associated <see cref="CancellationTokenSource"/> instance at the earliest opportunity (disposing
+ /// the source will dispose of this allocated handle). The handle should not be closed or disposed directly.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public WaitHandle WaitHandle => (_source ?? CancellationTokenSource.s_neverCanceledSource).WaitHandle;
+
+ // public CancellationToken()
+ // this constructor is implicit for structs
+ // -> this should behaves exactly as for new CancellationToken(false)
+
+ /// <summary>
+ /// Internal constructor only a CancellationTokenSource should create a CancellationToken
+ /// </summary>
+ internal CancellationToken(CancellationTokenSource source) => _source = source;
+
+ /// <summary>
+ /// Initializes the <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </summary>
+ /// <param name="canceled">
+ /// The canceled state for the token.
+ /// </param>
+ /// <remarks>
+ /// Tokens created with this constructor will remain in the canceled state specified
+ /// by the <paramref name="canceled"/> parameter. If <paramref name="canceled"/> is false,
+ /// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be false.
+ /// If <paramref name="canceled"/> is true,
+ /// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be true.
+ /// </remarks>
+ public CancellationToken(bool canceled) : this(canceled ? CancellationTokenSource.s_canceledSource : null)
+ {
+ }
+
+ /// <summary>
+ /// Registers a delegate that will be called when this <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to unregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ public CancellationTokenRegistration Register(Action callback) =>
+ Register(
+ s_actionToActionObjShunt,
+ callback ?? throw new ArgumentNullException(nameof(callback)),
+ useSynchronizationContext: false,
+ useExecutionContext: true);
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
+ /// when invoking the <paramref name="callback"/>.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to unregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext) =>
+ Register(
+ s_actionToActionObjShunt,
+ callback ?? throw new ArgumentNullException(nameof(callback)),
+ useSynchronizationContext,
+ useExecutionContext: true);
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to unregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ public CancellationTokenRegistration Register(Action<object> callback, object state) =>
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: true);
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists,
+ /// will be captured along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
+ /// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
+ /// when invoking the <paramref name="callback"/>.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to unregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext) =>
+ Register(callback, state, useSynchronizationContext, useExecutionContext: true);
+
+ // helper for internal registration needs that don't require an EC capture (e.g. creating linked token sources, or registering unstarted TPL tasks)
+ // has a handy signature, and skips capturing execution context.
+ internal CancellationTokenRegistration InternalRegisterWithoutEC(Action<object> callback, object state) =>
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: false);
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
+ /// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
+ /// when invoking the <paramref name="callback"/>.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to unregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+#if CORECLR
+ private
+#else
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public
+#endif
+ CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext, bool useExecutionContext)
+ {
+ if (callback == null)
+ throw new ArgumentNullException(nameof(callback));
+
+ CancellationTokenSource source = _source;
+ return source != null ?
+ source.InternalRegister(callback, state, useSynchronizationContext ? SynchronizationContext.Current : null, useExecutionContext ? ExecutionContext.Capture() : null) :
+ default; // Nothing to do for tokens than can never reach the canceled state. Give back a dummy registration.
+ }
+
+ /// <summary>
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// specified token.
+ /// </summary>
+ /// <param name="other">The other <see cref="T:System.Threading.CancellationToken">CancellationToken</see> to which to compare this
+ /// instance.</param>
+ /// <returns>True if the instances are equal; otherwise, false. Two tokens are equal if they are associated
+ /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
+ /// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
+ public bool Equals(CancellationToken other) => _source == other._source;
+
+ /// <summary>
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// specified <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="other">The other object to which to compare this instance.</param>
+ /// <returns>True if <paramref name="other"/> is a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
+ /// and if the two instances are equal; otherwise, false. Two tokens are equal if they are associated
+ /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
+ /// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">An associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public override bool Equals(object other) => other is CancellationToken && Equals((CancellationToken)other);
+
+ /// <summary>
+ /// Serves as a hash function for a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </summary>
+ /// <returns>A hash code for the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance.</returns>
+ public override int GetHashCode() => (_source ?? CancellationTokenSource.s_neverCanceledSource).GetHashCode();
+
+ /// <summary>
+ /// Determines whether two <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances are equal.
+ /// </summary>
+ /// <param name="left">The first instance.</param>
+ /// <param name="right">The second instance.</param>
+ /// <returns>True if the instances are equal; otherwise, false.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">An associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public static bool operator ==(CancellationToken left, CancellationToken right) => left.Equals(right);
+
+ /// <summary>
+ /// Determines whether two <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances are not equal.
+ /// </summary>
+ /// <param name="left">The first instance.</param>
+ /// <param name="right">The second instance.</param>
+ /// <returns>True if the instances are not equal; otherwise, false.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">An associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public static bool operator !=(CancellationToken left, CancellationToken right) => !left.Equals(right);
+
+ /// <summary>
+ /// Throws a <see cref="T:System.OperationCanceledException">OperationCanceledException</see> if
+ /// this token has had cancellation requested.
+ /// </summary>
+ /// <remarks>
+ /// This method provides functionality equivalent to:
+ /// <code>
+ /// if (token.IsCancellationRequested)
+ /// throw new OperationCanceledException(token);
+ /// </code>
+ /// </remarks>
+ /// <exception cref="System.OperationCanceledException">The token has had cancellation requested.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public void ThrowIfCancellationRequested()
+ {
+ if (IsCancellationRequested)
+ ThrowOperationCanceledException();
+ }
+
+ // Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
+ private void ThrowOperationCanceledException() =>
+ throw new OperationCanceledException(SR.OperationCanceled, this);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs
new file mode 100644
index 000000000..2da53b2b8
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs
@@ -0,0 +1,93 @@
+// 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.IO;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.Threading
+{
+ public partial class EventWaitHandle
+ {
+ private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.EVENT_MODIFY_STATE;
+
+ private EventWaitHandle(SafeWaitHandle handle)
+ {
+ SafeWaitHandle = handle;
+ }
+
+ private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew)
+ {
+#if !PLATFORM_WINDOWS
+ if (name != null)
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ uint eventFlags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0;
+ if (mode == EventResetMode.ManualReset)
+ eventFlags |= (uint)Interop.Kernel32.CREATE_EVENT_MANUAL_RESET;
+
+ SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(IntPtr.Zero, name, eventFlags, AccessRights);
+
+ int errorCode = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ {
+ handle.SetHandleAsInvalid();
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+ createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+ SafeWaitHandle = handle;
+ }
+
+ private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle result)
+ {
+#if PLATFORM_WINDOWS
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+ if (name.Length == 0)
+ throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+
+ result = null;
+ SafeWaitHandle myHandle = Interop.Kernel32.OpenEvent(AccessRights, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME)
+ return OpenExistingResult.NameNotFound;
+ if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND)
+ return OpenExistingResult.PathNotFound;
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ return OpenExistingResult.NameInvalid;
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+ result = new EventWaitHandle(myHandle);
+ return OpenExistingResult.Success;
+#else
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ }
+
+ public bool Reset()
+ {
+ bool res = Interop.Kernel32.ResetEvent(_waitHandle);
+ if (!res)
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ return res;
+ }
+
+ public bool Set()
+ {
+ bool res = Interop.Kernel32.SetEvent(_waitHandle);
+ if (!res)
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ return res;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs
new file mode 100644
index 000000000..4cd733b9b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs
@@ -0,0 +1,51 @@
+// 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.IO;
+
+namespace System.Threading
+{
+ public partial class EventWaitHandle : WaitHandle
+ {
+ public EventWaitHandle(bool initialState, EventResetMode mode) :
+ this(initialState, mode, null, out _)
+ {
+ }
+
+ public EventWaitHandle(bool initialState, EventResetMode mode, string name) :
+ this(initialState, mode, name, out _)
+ {
+ }
+
+ public EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew)
+ {
+ if (mode != EventResetMode.AutoReset && mode != EventResetMode.ManualReset)
+ throw new ArgumentException(SR.Argument_InvalidFlag, nameof(mode));
+
+ CreateEventCore(initialState, mode, name, out createdNew);
+ }
+
+ public static EventWaitHandle OpenExisting(string name)
+ {
+ EventWaitHandle result;
+ switch (OpenExistingWorker(name, out result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+ case OpenExistingResult.PathNotFound:
+ throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name));
+ default:
+ return result;
+ }
+ }
+
+ public static bool TryOpenExisting(string name, out EventWaitHandle result)
+ {
+ return OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
index 9f27c6dcb..694514ef0 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
@@ -19,11 +19,12 @@ using Thread = Internal.Runtime.Augments.RuntimeThread;
namespace System.Threading
{
- public delegate void ContextCallback(Object state);
+ public delegate void ContextCallback(object state);
public sealed class ExecutionContext : IDisposable, ISerializable
{
internal static readonly ExecutionContext Default = new ExecutionContext(isDefault: true);
+ internal static readonly ExecutionContext DefaultFlowSuppressed = new ExecutionContext(AsyncLocalValueMap.Empty, Array.Empty<IAsyncLocal>(), isFlowSuppressed: true);
private readonly IAsyncLocalValueMap m_localValues;
private readonly IAsyncLocal[] m_localChangeNotifications;
@@ -63,15 +64,14 @@ namespace System.Threading
{
Debug.Assert(isFlowSuppressed != m_isFlowSuppressed);
- if (!isFlowSuppressed &&
- (m_localValues == null ||
- m_localValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap))
- )
+ if (m_localValues == null || AsyncLocalValueMap.IsEmpty(m_localValues))
{
- return null; // implies the default context
+ return isFlowSuppressed ?
+ DefaultFlowSuppressed :
+ null; // implies the default context
}
- // Flow suppressing a Default context will have null values, set them to Empty
- return new ExecutionContext(m_localValues ?? AsyncLocalValueMap.Empty, m_localChangeNotifications ?? Array.Empty<IAsyncLocal>(), isFlowSuppressed);
+
+ return new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed);
}
public static AsyncFlowControl SuppressFlow()
@@ -112,7 +112,7 @@ namespace System.Threading
internal bool IsDefault => m_isDefault;
- public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state)
+ public static void Run(ExecutionContext executionContext, ContextCallback callback, object state)
{
// Note: ExecutionContext.Run is an extremely hot function and used by every await, ThreadPool execution, etc.
if (executionContext == null)
@@ -123,7 +123,7 @@ namespace System.Threading
RunInternal(executionContext, callback, state);
}
- internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
+ internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, object state)
{
// Note: ExecutionContext.RunInternal is an extremely hot function and used by every await, ThreadPool execution, etc.
// Note: Manual enregistering may be addressed by "Exception Handling Write Through Optimization"
@@ -321,19 +321,26 @@ namespace System.Threading
return;
}
+ // Regarding 'treatNullValueAsNonexistent: !needChangeNotifications' below:
+ // - When change notifications are not necessary for this IAsyncLocal, there is no observable difference between
+ // storing a null value and removing the IAsyncLocal from 'm_localValues'
+ // - When change notifications are necessary for this IAsyncLocal, the IAsyncLocal's absence in 'm_localValues'
+ // indicates that this is the first value change for the IAsyncLocal and it needs to be registered for change
+ // notifications. So in this case, a null value must be stored in 'm_localValues' to indicate that the IAsyncLocal
+ // is already registered for change notifications.
IAsyncLocal[] newChangeNotifications = null;
IAsyncLocalValueMap newValues;
bool isFlowSuppressed = false;
if (current != null)
{
isFlowSuppressed = current.m_isFlowSuppressed;
- newValues = current.m_localValues.Set(local, newValue);
+ newValues = current.m_localValues.Set(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
newChangeNotifications = current.m_localChangeNotifications;
}
else
{
// First AsyncLocal
- newValues = new AsyncLocalValueMap.OneElementAsyncLocalValueMap(local, newValue);
+ newValues = AsyncLocalValueMap.Create(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
}
//
@@ -359,7 +366,7 @@ namespace System.Threading
}
Thread.CurrentThread.ExecutionContext =
- (!isFlowSuppressed && newValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap)) ?
+ (!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
null : // No values, return to Default context
new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs
new file mode 100644
index 000000000..dc65f6f16
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs
@@ -0,0 +1,759 @@
+// 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.Diagnostics;
+
+namespace System.Threading
+{
+ // ManualResetEventSlim wraps a manual-reset event internally with a little bit of
+ // spinning. When an event will be set imminently, it is often advantageous to avoid
+ // a 4k+ cycle context switch in favor of briefly spinning. Therefore we layer on to
+ // a brief amount of spinning that should, on the average, make using the slim event
+ // cheaper than using Win32 events directly. This can be reset manually, much like
+ // a Win32 manual-reset would be.
+ //
+ // Notes:
+ // We lazily allocate the Win32 event internally. Therefore, the caller should
+ // always call Dispose to clean it up, just in case. This API is a no-op of the
+ // event wasn't allocated, but if it was, ensures that the event goes away
+ // eagerly, instead of waiting for finalization.
+
+ /// <summary>
+ /// Provides a slimmed down version of <see cref="T:System.Threading.ManualResetEvent"/>.
+ /// </summary>
+ /// <remarks>
+ /// All public and protected members of <see cref="ManualResetEventSlim"/> are thread-safe and may be used
+ /// concurrently from multiple threads, with the exception of Dispose, which
+ /// must only be used when all other operations on the <see cref="ManualResetEventSlim"/> have
+ /// completed, and Reset, which should only be used when no other threads are
+ /// accessing the event.
+ /// </remarks>
+ [DebuggerDisplay("Set = {IsSet}")]
+ public class ManualResetEventSlim : IDisposable
+ {
+ // These are the default spin counts we use on single-proc and MP machines.
+ private const int DEFAULT_SPIN_SP = 1;
+
+ private volatile object m_lock;
+ // A lock used for waiting and pulsing. Lazily initialized via EnsureLockObjectCreated()
+
+ private volatile ManualResetEvent m_eventObj; // A true Win32 event used for waiting.
+
+ // -- State -- //
+ //For a packed word a uint would seem better, but Interlocked.* doesn't support them as uint isn't CLS-compliant.
+ private volatile int m_combinedState; //ie a uint. Used for the state items listed below.
+
+ //1-bit for signalled state
+ private const int SignalledState_BitMask = unchecked((int)0x80000000);//1000 0000 0000 0000 0000 0000 0000 0000
+ private const int SignalledState_ShiftCount = 31;
+
+ //1-bit for disposed state
+ private const int Dispose_BitMask = unchecked((int)0x40000000);//0100 0000 0000 0000 0000 0000 0000 0000
+
+ //11-bits for m_spinCount
+ private const int SpinCountState_BitMask = unchecked((int)0x3FF80000); //0011 1111 1111 1000 0000 0000 0000 0000
+ private const int SpinCountState_ShiftCount = 19;
+ private const int SpinCountState_MaxValue = (1 << 11) - 1; //2047
+
+ //19-bits for m_waiters. This allows support of 512K threads waiting which should be ample
+ private const int NumWaitersState_BitMask = unchecked((int)0x0007FFFF); // 0000 0000 0000 0111 1111 1111 1111 1111
+ private const int NumWaitersState_ShiftCount = 0;
+ private const int NumWaitersState_MaxValue = (1 << 19) - 1; //512K-1
+ // ----------- //
+
+#if DEBUG
+ private static int s_nextId; // The next id that will be given out.
+ private int m_id = Interlocked.Increment(ref s_nextId); // A unique id for debugging purposes only.
+ private long m_lastSetTime;
+ private long m_lastResetTime;
+#endif
+
+ /// <summary>
+ /// Gets the underlying <see cref="T:System.Threading.WaitHandle"/> object for this <see
+ /// cref="ManualResetEventSlim"/>.
+ /// </summary>
+ /// <value>The underlying <see cref="T:System.Threading.WaitHandle"/> event object fore this <see
+ /// cref="ManualResetEventSlim"/>.</value>
+ /// <remarks>
+ /// Accessing this property forces initialization of an underlying event object if one hasn't
+ /// already been created. To simply wait on this <see cref="ManualResetEventSlim"/>,
+ /// the public Wait methods should be preferred.
+ /// </remarks>
+ public WaitHandle WaitHandle
+ {
+ get
+ {
+ ThrowIfDisposed();
+ if (m_eventObj == null)
+ {
+ // Lazily initialize the event object if needed.
+ LazyInitializeEvent();
+ }
+
+ return m_eventObj;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the event is set.
+ /// </summary>
+ /// <value>true if the event has is set; otherwise, false.</value>
+ public bool IsSet
+ {
+ get
+ {
+ return 0 != ExtractStatePortion(m_combinedState, SignalledState_BitMask);
+ }
+
+ private set
+ {
+ UpdateStateAtomically(((value) ? 1 : 0) << SignalledState_ShiftCount, SignalledState_BitMask);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of spin waits that will be occur before falling back to a true wait.
+ /// </summary>
+ public int SpinCount
+ {
+ get
+ {
+ return ExtractStatePortionAndShiftRight(m_combinedState, SpinCountState_BitMask, SpinCountState_ShiftCount);
+ }
+
+ private set
+ {
+ Debug.Assert(value >= 0, "SpinCount is a restricted-width integer. The value supplied is outside the legal range.");
+ Debug.Assert(value <= SpinCountState_MaxValue, "SpinCount is a restricted-width integer. The value supplied is outside the legal range.");
+ // Don't worry about thread safety because it's set one time from the constructor
+ m_combinedState = (m_combinedState & ~SpinCountState_BitMask) | (value << SpinCountState_ShiftCount);
+ }
+ }
+
+ /// <summary>
+ /// How many threads are waiting.
+ /// </summary>
+ private int Waiters
+ {
+ get
+ {
+ return ExtractStatePortionAndShiftRight(m_combinedState, NumWaitersState_BitMask, NumWaitersState_ShiftCount);
+ }
+
+ set
+ {
+ //setting to <0 would indicate an internal flaw, hence Assert is appropriate.
+ Debug.Assert(value >= 0, "NumWaiters should never be less than zero. This indicates an internal error.");
+
+ // it is possible for the max number of waiters to be exceeded via user-code, hence we use a real exception here.
+ if (value >= NumWaitersState_MaxValue)
+ throw new InvalidOperationException(string.Format(SR.ManualResetEventSlim_ctor_TooManyWaiters, NumWaitersState_MaxValue));
+
+ UpdateStateAtomically(value << NumWaitersState_ShiftCount, NumWaitersState_BitMask);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------
+ // Constructs a new event, optionally specifying the initial state and spin count.
+ // The defaults are that the event is unsignaled and some reasonable default spin.
+ //
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with an initial state of nonsignaled.
+ /// </summary>
+ public ManualResetEventSlim()
+ : this(false)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with a boolean value indicating whether to set the initial state to signaled.
+ /// </summary>
+ /// <param name="initialState">true to set the initial state signaled; false to set the initial state
+ /// to nonsignaled.</param>
+ public ManualResetEventSlim(bool initialState)
+ {
+ // Specify the default spin count, and use default spin if we're
+ // on a multi-processor machine. Otherwise, we won't.
+ Initialize(initialState, SpinWait.SpinCountforSpinBeforeWait);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with a Boolean value indicating whether to set the initial state to signaled and a specified
+ /// spin count.
+ /// </summary>
+ /// <param name="initialState">true to set the initial state to signaled; false to set the initial state
+ /// to nonsignaled.</param>
+ /// <param name="spinCount">The number of spin waits that will occur before falling back to a true
+ /// wait.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="spinCount"/> is less than
+ /// 0 or greater than the maximum allowed value.</exception>
+ public ManualResetEventSlim(bool initialState, int spinCount)
+ {
+ if (spinCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(spinCount));
+ }
+
+ if (spinCount > SpinCountState_MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(spinCount),
+ string.Format(SR.ManualResetEventSlim_ctor_SpinCountOutOfRange, SpinCountState_MaxValue));
+ }
+
+ // We will suppress default spin because the user specified a count.
+ Initialize(initialState, spinCount);
+ }
+
+ /// <summary>
+ /// Initializes the internal state of the event.
+ /// </summary>
+ /// <param name="initialState">Whether the event is set initially or not.</param>
+ /// <param name="spinCount">The spin count that decides when the event will block.</param>
+ private void Initialize(bool initialState, int spinCount)
+ {
+ m_combinedState = initialState ? (1 << SignalledState_ShiftCount) : 0;
+ //the spinCount argument has been validated by the ctors.
+ //but we now sanity check our predefined constants.
+ Debug.Assert(DEFAULT_SPIN_SP >= 0, "Internal error - DEFAULT_SPIN_SP is outside the legal range.");
+ Debug.Assert(DEFAULT_SPIN_SP <= SpinCountState_MaxValue, "Internal error - DEFAULT_SPIN_SP is outside the legal range.");
+
+ SpinCount = PlatformHelper.IsSingleProcessor ? DEFAULT_SPIN_SP : spinCount;
+ }
+
+ /// <summary>
+ /// Helper to ensure the lock object is created before first use.
+ /// </summary>
+ private void EnsureLockObjectCreated()
+ {
+ if (m_lock != null)
+ return;
+
+ object newObj = new object();
+ Interlocked.CompareExchange(ref m_lock, newObj, null); // failure is benign. Someone else set the value.
+ }
+
+ /// <summary>
+ /// This method lazily initializes the event object. It uses CAS to guarantee that
+ /// many threads racing to call this at once don't result in more than one event
+ /// being stored and used. The event will be signaled or unsignaled depending on
+ /// the state of the thin-event itself, with synchronization taken into account.
+ /// </summary>
+ /// <returns>True if a new event was created and stored, false otherwise.</returns>
+ private bool LazyInitializeEvent()
+ {
+ bool preInitializeIsSet = IsSet;
+ ManualResetEvent newEventObj = new ManualResetEvent(preInitializeIsSet);
+
+ // We have to CAS this in case we are racing with another thread. We must
+ // guarantee only one event is actually stored in this field.
+ if (Interlocked.CompareExchange(ref m_eventObj, newEventObj, null) != null)
+ {
+ // Someone else set the value due to a race condition. Destroy the garbage event.
+ newEventObj.Dispose();
+
+ return false;
+ }
+ else
+ {
+ // Now that the event is published, verify that the state hasn't changed since
+ // we snapped the preInitializeState. Another thread could have done that
+ // between our initial observation above and here. The barrier incurred from
+ // the CAS above (in addition to m_state being volatile) prevents this read
+ // from moving earlier and being collapsed with our original one.
+ bool currentIsSet = IsSet;
+ if (currentIsSet != preInitializeIsSet)
+ {
+ Debug.Assert(currentIsSet,
+ "The only safe concurrent transition is from unset->set: detected set->unset.");
+
+ // We saw it as unsignaled, but it has since become set.
+ lock (newEventObj)
+ {
+ // If our event hasn't already been disposed of, we must set it.
+ if (m_eventObj == newEventObj)
+ {
+ newEventObj.Set();
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Sets the state of the event to signaled, which allows one or more threads waiting on the event to
+ /// proceed.
+ /// </summary>
+ public void Set()
+ {
+ Set(false);
+ }
+
+ /// <summary>
+ /// Private helper to actually perform the Set.
+ /// </summary>
+ /// <param name="duringCancellation">Indicates whether we are calling Set() during cancellation.</param>
+ /// <exception cref="T:System.OperationCanceledException">The object has been canceled.</exception>
+ private void Set(bool duringCancellation)
+ {
+ // We need to ensure that IsSet=true does not get reordered past the read of m_eventObj
+ // This would be a legal movement according to the .NET memory model.
+ // The code is safe as IsSet involves an Interlocked.CompareExchange which provides a full memory barrier.
+ IsSet = true;
+
+ // If there are waiting threads, we need to pulse them.
+ if (Waiters > 0)
+ {
+ Debug.Assert(m_lock != null); //if waiters>0, then m_lock has already been created.
+ lock (m_lock)
+ {
+ Monitor.PulseAll(m_lock);
+ }
+ }
+
+ ManualResetEvent eventObj = m_eventObj;
+
+ //Design-decision: do not set the event if we are in cancellation -> better to deadlock than to wake up waiters incorrectly
+ //It would be preferable to wake up the event and have it throw OCE. This requires MRE to implement cancellation logic
+
+ if (eventObj != null && !duringCancellation)
+ {
+ // We must surround this call to Set in a lock. The reason is fairly subtle.
+ // Sometimes a thread will issue a Wait and wake up after we have set m_state,
+ // but before we have gotten around to setting m_eventObj (just below). That's
+ // because Wait first checks m_state and will only access the event if absolutely
+ // necessary. However, the coding pattern { event.Wait(); event.Dispose() } is
+ // quite common, and we must support it. If the waiter woke up and disposed of
+ // the event object before the setter has finished, however, we would try to set a
+ // now-disposed Win32 event. Crash! To deal with this race condition, we use a lock to
+ // protect access to the event object when setting and disposing of it. We also
+ // double-check that the event has not become null in the meantime when in the lock.
+
+ lock (eventObj)
+ {
+ if (m_eventObj != null)
+ {
+ // If somebody is waiting, we must set the event.
+ m_eventObj.Set();
+ }
+ }
+ }
+
+#if DEBUG
+ m_lastSetTime = DateTime.UtcNow.Ticks;
+#endif
+ }
+
+ /// <summary>
+ /// Sets the state of the event to nonsignaled, which causes threads to block.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Reset()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Reset()
+ {
+ ThrowIfDisposed();
+ // If there's an event, reset it.
+ if (m_eventObj != null)
+ {
+ m_eventObj.Reset();
+ }
+
+ // There is a race condition here. If another thread Sets the event, we will get into a state
+ // where m_state will be unsignaled, yet the Win32 event object will have been signaled.
+ // This could cause waiting threads to wake up even though the event is in an
+ // unsignaled state. This is fine -- those that are calling Reset concurrently are
+ // responsible for doing "the right thing" -- e.g. rechecking the condition and
+ // resetting the event manually.
+
+ // And finally set our state back to unsignaled.
+ IsSet = false;
+
+#if DEBUG
+ m_lastResetTime = DateTime.UtcNow.Ticks;
+#endif
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ public void Wait()
+ {
+ Wait(Timeout.Infinite, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> receives a signal,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledExcepton"><paramref name="cancellationToken"/> was
+ /// canceled.</exception>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(timeout));
+ }
+
+ return Wait((int)totalMilliseconds, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.Threading.OperationCanceledException"><paramref
+ /// name="cancellationToken"/> was canceled.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(timeout));
+ }
+
+ return Wait((int)totalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// 32-bit signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// 32-bit signed integer to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <exception cref="T:System.Threading.OperationCanceledException"><paramref
+ /// name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ ThrowIfDisposed();
+ cancellationToken.ThrowIfCancellationRequested(); // an early convenience check
+
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout));
+ }
+
+ if (!IsSet)
+ {
+ if (millisecondsTimeout == 0)
+ {
+ // For 0-timeouts, we just return immediately.
+ return false;
+ }
+
+
+ // We spin briefly before falling back to allocating and/or waiting on a true event.
+ uint startTime = 0;
+ bool bNeedTimeoutAdjustment = false;
+ int realMillisecondsTimeout = millisecondsTimeout; //this will be adjusted if necessary.
+
+ if (millisecondsTimeout != Timeout.Infinite)
+ {
+ // We will account for time spent spinning, so that we can decrement it from our
+ // timeout. In most cases the time spent in this section will be negligible. But
+ // we can't discount the possibility of our thread being switched out for a lengthy
+ // period of time. The timeout adjustments only take effect when and if we actually
+ // decide to block in the kernel below.
+
+ startTime = TimeoutHelper.GetTime();
+ bNeedTimeoutAdjustment = true;
+ }
+
+ // Spin
+ int spinCount = SpinCount;
+ var spinner = new SpinWait();
+ while (spinner.Count < spinCount)
+ {
+ spinner.SpinOnce(SpinWait.Sleep1ThresholdForLongSpinBeforeWait);
+
+ if (IsSet)
+ {
+ return true;
+ }
+
+ if (spinner.Count >= 100 && spinner.Count % 10 == 0) // check the cancellation token if the user passed a very large spin count
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+
+ // Now enter the lock and wait.
+ EnsureLockObjectCreated();
+
+ // We must register and unregister the token outside of the lock, to avoid deadlocks.
+ using (cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCallback, this))
+ {
+ lock (m_lock)
+ {
+ // Loop to cope with spurious wakeups from other waits being canceled
+ while (!IsSet)
+ {
+ // If our token was canceled, we must throw and exit.
+ cancellationToken.ThrowIfCancellationRequested();
+
+ //update timeout (delays in wait commencement are due to spinning and/or spurious wakeups from other waits being canceled)
+ if (bNeedTimeoutAdjustment)
+ {
+ realMillisecondsTimeout = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
+ if (realMillisecondsTimeout <= 0)
+ return false;
+ }
+
+ // There is a race condition that Set will fail to see that there are waiters as Set does not take the lock,
+ // so after updating waiters, we must check IsSet again.
+ // Also, we must ensure there cannot be any reordering of the assignment to Waiters and the
+ // read from IsSet. This is guaranteed as Waiters{set;} involves an Interlocked.CompareExchange
+ // operation which provides a full memory barrier.
+ // If we see IsSet=false, then we are guaranteed that Set() will see that we are
+ // waiting and will pulse the monitor correctly.
+
+ Waiters = Waiters + 1;
+
+ if (IsSet) //This check must occur after updating Waiters.
+ {
+ Waiters--; //revert the increment.
+ return true;
+ }
+
+ // Now finally perform the wait.
+ try
+ {
+ // ** the actual wait **
+ if (!Monitor.Wait(m_lock, realMillisecondsTimeout))
+ return false; //return immediately if the timeout has expired.
+ }
+ finally
+ {
+ // Clean up: we're done waiting.
+ Waiters = Waiters - 1;
+ }
+ // Now just loop back around, and the right thing will happen. Either:
+ // 1. We had a spurious wake-up due to some other wait being canceled via a different cancellationToken (rewait)
+ // or 2. the wait was successful. (the loop will break)
+ }
+ }
+ }
+ } // automatically disposes (and unregisters) the callback
+
+ return true; //done. The wait was satisfied.
+ }
+
+ /// <summary>
+ /// Releases all resources used by the current instance of <see cref="ManualResetEventSlim"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// <see cref="ManualResetEventSlim"/>, and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose(bool)"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if ((m_combinedState & Dispose_BitMask) != 0)
+ return; // already disposed
+
+ m_combinedState |= Dispose_BitMask; //set the dispose bit
+ if (disposing)
+ {
+ // We will dispose of the event object. We do this under a lock to protect
+ // against the race condition outlined in the Set method above.
+ ManualResetEvent eventObj = m_eventObj;
+ if (eventObj != null)
+ {
+ lock (eventObj)
+ {
+ eventObj.Dispose();
+ m_eventObj = null;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Throw ObjectDisposedException if the MRES is disposed
+ /// </summary>
+ private void ThrowIfDisposed()
+ {
+ if ((m_combinedState & Dispose_BitMask) != 0)
+ throw new ObjectDisposedException(SR.ManualResetEventSlim_Disposed);
+ }
+
+ /// <summary>
+ /// Private helper method to wake up waiters when a cancellationToken gets canceled.
+ /// </summary>
+ private static Action<object> s_cancellationTokenCallback = new Action<object>(CancellationTokenCallback);
+ private static void CancellationTokenCallback(object obj)
+ {
+ ManualResetEventSlim mre = obj as ManualResetEventSlim;
+ Debug.Assert(mre != null, "Expected a ManualResetEventSlim");
+ Debug.Assert(mre.m_lock != null); //the lock should have been created before this callback is registered for use.
+ lock (mre.m_lock)
+ {
+ Monitor.PulseAll(mre.m_lock); // awaken all waiters
+ }
+ }
+
+ /// <summary>
+ /// Private helper method for updating parts of a bit-string state value.
+ /// Mainly called from the IsSet and Waiters properties setters
+ /// </summary>
+ /// <remarks>
+ /// Note: the parameter types must be int as CompareExchange cannot take a Uint
+ /// </remarks>
+ /// <param name="newBits">The new value</param>
+ /// <param name="updateBitsMask">The mask used to set the bits</param>
+ private void UpdateStateAtomically(int newBits, int updateBitsMask)
+ {
+ SpinWait sw = new SpinWait();
+
+ Debug.Assert((newBits | updateBitsMask) == updateBitsMask, "newBits do not fall within the updateBitsMask.");
+
+ do
+ {
+ int oldState = m_combinedState; // cache the old value for testing in CAS
+
+ // Procedure:(1) zero the updateBits. eg oldState = [11111111] flag= [00111000] newState = [11000111]
+ // then (2) map in the newBits. eg [11000111] newBits=00101000, newState=[11101111]
+ int newState = (oldState & ~updateBitsMask) | newBits;
+
+ if (Interlocked.CompareExchange(ref m_combinedState, newState, oldState) == oldState)
+ {
+ return;
+ }
+
+ sw.SpinOnce();
+ } while (true);
+ }
+
+ /// <summary>
+ /// Private helper method - performs Mask and shift, particular helpful to extract a field from a packed word.
+ /// eg ExtractStatePortionAndShiftRight(0x12345678, 0xFF000000, 24) => 0x12, ie extracting the top 8-bits as a simple integer
+ ///
+ /// ?? is there a common place to put this rather than being private to MRES?
+ /// </summary>
+ /// <param name="state"></param>
+ /// <param name="mask"></param>
+ /// <param name="rightBitShiftCount"></param>
+ /// <returns></returns>
+ private static int ExtractStatePortionAndShiftRight(int state, int mask, int rightBitShiftCount)
+ {
+ //convert to uint before shifting so that right-shift does not replicate the sign-bit,
+ //then convert back to int.
+ return unchecked((int)(((uint)(state & mask)) >> rightBitShiftCount));
+ }
+
+ /// <summary>
+ /// Performs a Mask operation, but does not perform the shift.
+ /// This is acceptable for boolean values for which the shift is unnecessary
+ /// eg (val &amp; Mask) != 0 is an appropriate way to extract a boolean rather than using
+ /// ((val &amp; Mask) &gt;&gt; shiftAmount) == 1
+ ///
+ /// ?? is there a common place to put this rather than being private to MRES?
+ /// </summary>
+ /// <param name="state"></param>
+ /// <param name="mask"></param>
+ private static int ExtractStatePortion(int state, int mask)
+ {
+ return state & mask;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs
new file mode 100644
index 000000000..212eb9dc3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs
@@ -0,0 +1,100 @@
+// 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.IO;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Synchronization primitive that can also be used for interprocess synchronization
+ /// </summary>
+ public sealed partial class Mutex : WaitHandle
+ {
+ private const uint AccessRights =
+ (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.MUTEX_MODIFY_STATE;
+
+ private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew)
+ {
+ uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0;
+ SafeWaitHandle mutexHandle = Interop.Kernel32.CreateMutexEx(IntPtr.Zero, name, mutexFlags, AccessRights);
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (mutexHandle.IsInvalid)
+ {
+ mutexHandle.SetHandleAsInvalid();
+#if !PLATFORM_WINDOWS
+ if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE)
+ // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
+ throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name));
+#endif
+ if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+
+ createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+ SafeWaitHandle = mutexHandle;
+ }
+
+ private static OpenExistingResult OpenExistingWorker(string name, out Mutex result)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ if (name.Length == 0)
+ {
+ throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+ }
+
+ result = null;
+ // To allow users to view & edit the ACL's, call OpenMutex
+ // with parameters to allow us to view & edit the ACL. This will
+ // fail if we don't have permission to view or edit the ACL's.
+ // If that happens, ask for less permissions.
+ SafeWaitHandle myHandle = Interop.Kernel32.OpenMutex(AccessRights, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+#if !PLATFORM_WINDOWS
+ if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE)
+ {
+ // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
+ throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name));
+ }
+#endif
+ if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
+ return OpenExistingResult.NameNotFound;
+ if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
+ return OpenExistingResult.PathNotFound;
+ if (Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
+ return OpenExistingResult.NameInvalid;
+
+ // this is for passed through Win32Native Errors
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+
+ result = new Mutex(myHandle);
+ return OpenExistingResult.Success;
+ }
+
+ // Note: To call ReleaseMutex, you must have an ACL granting you
+ // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value
+ // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001).
+ public void ReleaseMutex()
+ {
+ if (!Interop.Kernel32.ReleaseMutex(_waitHandle))
+ {
+ throw new ApplicationException(SR.Arg_SynchronizationLockException);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs b/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs
new file mode 100644
index 000000000..d85242892
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs
@@ -0,0 +1,62 @@
+// 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.IO;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Synchronization primitive that can also be used for interprocess synchronization
+ /// </summary>
+ public sealed partial class Mutex : WaitHandle
+ {
+ public Mutex(bool initiallyOwned, string name, out bool createdNew)
+ {
+ CreateMutexCore(initiallyOwned, name, out createdNew);
+ }
+
+ public Mutex(bool initiallyOwned, string name)
+ {
+ CreateMutexCore(initiallyOwned, name, out _);
+ }
+
+ public Mutex(bool initiallyOwned)
+ {
+ CreateMutexCore(initiallyOwned, null, out _);
+ }
+
+ public Mutex()
+ {
+ CreateMutexCore(false, null, out _);
+ }
+
+ private Mutex(SafeWaitHandle handle)
+ {
+ SafeWaitHandle = handle;
+ }
+
+ public static Mutex OpenExisting(string name)
+ {
+ switch (OpenExistingWorker(name, out Mutex result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+ case OpenExistingResult.PathNotFound:
+ throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name));
+
+ default:
+ return result;
+ }
+ }
+
+ public static bool TryOpenExisting(string name, out Mutex result) =>
+ OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs b/src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs
new file mode 100644
index 000000000..933cb81ec
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs
@@ -0,0 +1,18 @@
+// 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.Runtime.InteropServices;
+
+namespace System.Threading
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NativeOverlapped
+ {
+ public IntPtr InternalLow;
+ public IntPtr InternalHigh;
+ public int OffsetLow;
+ public int OffsetHigh;
+ public IntPtr EventHandle;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs
index 45175488e..9424fbd5b 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs
@@ -241,7 +241,7 @@ namespace System.Threading
public TimeoutTracker(TimeSpan timeout)
{
long ltm = (long)timeout.TotalMilliseconds;
- if (ltm < -1 || ltm > (long)Int32.MaxValue)
+ if (ltm < -1 || ltm > (long)int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(timeout));
_total = (int)ltm;
if (_total != -1 && _total != 0)
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs
new file mode 100644
index 000000000..8a14f5ef3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs
@@ -0,0 +1,88 @@
+// 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 Microsoft.Win32.SafeHandles;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Threading
+{
+ public sealed partial class Semaphore
+ {
+ private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.SEMAPHORE_MODIFY_STATE;
+
+ private Semaphore(SafeWaitHandle handle)
+ {
+ SafeWaitHandle = handle;
+ }
+
+ private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
+ {
+ Debug.Assert(initialCount >= 0);
+ Debug.Assert(maximumCount >= 1);
+ Debug.Assert(initialCount <= maximumCount);
+
+#if !PLATFORM_WINDOWS
+ if (name != null)
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ SafeWaitHandle myHandle = Interop.Kernel32.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights);
+
+ int errorCode = Marshal.GetLastWin32Error();
+ if (myHandle.IsInvalid)
+ {
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ throw new WaitHandleCannotBeOpenedException(
+ SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ }
+ createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+ this.SafeWaitHandle = myHandle;
+ }
+
+ private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
+ {
+#if PLATFORM_WINDOWS
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+ if (name.Length == 0)
+ throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+
+ // Pass false to OpenSemaphore to prevent inheritedHandles
+ SafeWaitHandle myHandle = Interop.Kernel32.OpenSemaphore(AccessRights, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ result = null;
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME)
+ return OpenExistingResult.NameNotFound;
+ if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND)
+ return OpenExistingResult.PathNotFound;
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ return OpenExistingResult.NameInvalid;
+ // this is for passed through NativeMethods Errors
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ }
+
+ result = new Semaphore(myHandle);
+ return OpenExistingResult.Success;
+#else
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ }
+
+ private int ReleaseCore(int releaseCount)
+ {
+ int previousCount;
+ if (!Interop.Kernel32.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount))
+ throw new SemaphoreFullException();
+
+ return previousCount;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs
new file mode 100644
index 000000000..6014fcd1c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs
@@ -0,0 +1,67 @@
+// 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 Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Threading
+{
+ public sealed partial class Semaphore : WaitHandle
+ {
+ // creates a nameless semaphore object
+ // Win32 only takes maximum count of int.MaxValue
+ public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { }
+
+ public Semaphore(int initialCount, int maximumCount, string name) :
+ this(initialCount, maximumCount, name, out _)
+ {
+ }
+
+ public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
+ {
+ if (initialCount < 0)
+ throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (maximumCount < 1)
+ throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedPosNum);
+
+ if (initialCount > maximumCount)
+ throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
+
+ CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew);
+ }
+
+ public static Semaphore OpenExisting(string name)
+ {
+ Semaphore result;
+ switch (OpenExistingWorker(name, out result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+ case OpenExistingResult.PathNotFound:
+ throw new IOException(SR.Format(SR.IO_PathNotFound_Path, name));
+ default:
+ return result;
+ }
+ }
+
+ public static bool TryOpenExisting(string name, out Semaphore result) =>
+ OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+
+ public int Release() => ReleaseCore(1);
+
+ // increase the count on a semaphore, returns previous count
+ public int Release(int releaseCount)
+ {
+ if (releaseCount < 1)
+ throw new ArgumentOutOfRangeException(nameof(releaseCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+ return ReleaseCore(releaseCount);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs
index 18558b19e..a6cff781d 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs
@@ -15,11 +15,11 @@ namespace System.Threading
{
}
- public SemaphoreFullException(String message) : base(message)
+ public SemaphoreFullException(string message) : base(message)
{
}
- public SemaphoreFullException(String message, Exception innerException) : base(message, innerException)
+ public SemaphoreFullException(string message, Exception innerException) : base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
new file mode 100644
index 000000000..83f5f1d28
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
@@ -0,0 +1,945 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Limits the number of threads that can access a resource or pool of resources concurrently.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="SemaphoreSlim"/> provides a lightweight semaphore class that doesn't
+ /// use Windows kernel semaphores.
+ /// </para>
+ /// <para>
+ /// All public and protected members of <see cref="SemaphoreSlim"/> are thread-safe and may be used
+ /// concurrently from multiple threads, with the exception of Dispose, which
+ /// must only be used when all other operations on the <see cref="SemaphoreSlim"/> have
+ /// completed.
+ /// </para>
+ /// </remarks>
+ [DebuggerDisplay("Current Count = {m_currentCount}")]
+ public class SemaphoreSlim : IDisposable
+ {
+ #region Private Fields
+
+ // The semaphore count, initialized in the constructor to the initial value, every release call incremetns it
+ // and every wait call decrements it as long as its value is positive otherwise the wait will block.
+ // Its value must be between the maximum semaphore value and zero
+ private volatile int m_currentCount;
+
+ // The maximum semaphore value, it is initialized to Int.MaxValue if the client didn't specify it. it is used
+ // to check if the count excceeded the maxi value or not.
+ private readonly int m_maxCount;
+
+ // The number of synchronously waiting threads, it is set to zero in the constructor and increments before blocking the
+ // threading and decrements it back after that. It is used as flag for the release call to know if there are
+ // waiting threads in the monitor or not.
+ private int m_waitCount;
+
+ /// <summary>
+ /// This is used to help prevent waking more waiters than necessary. It's not perfect and sometimes more waiters than
+ /// necessary may still be woken, see <see cref="WaitUntilCountOrTimeout"/>.
+ /// </summary>
+ private int m_countOfWaitersPulsedToWake;
+
+ // Dummy object used to in lock statements to protect the semaphore count, wait handle and cancelation
+ private object m_lockObj;
+
+ // Act as the semaphore wait handle, it's lazily initialized if needed, the first WaitHandle call initialize it
+ // and wait an release sets and resets it respectively as long as it is not null
+ private volatile ManualResetEvent m_waitHandle;
+
+ // Head of list representing asynchronous waits on the semaphore.
+ private TaskNode m_asyncHead;
+
+ // Tail of list representing asynchronous waits on the semaphore.
+ private TaskNode m_asyncTail;
+
+ // A pre-completed task with Result==true
+ private static readonly Task<bool> s_trueTask =
+ new Task<bool>(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
+ // A pre-completed task with Result==false
+ private readonly static Task<bool> s_falseTask =
+ new Task<bool>(false, false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
+
+ // No maximum constant
+ private const int NO_MAXIMUM = int.MaxValue;
+
+ // Task in a linked list of asynchronous waiters
+ private sealed class TaskNode : Task<bool>, IThreadPoolWorkItem
+ {
+ internal TaskNode Prev, Next;
+ internal TaskNode() : base() { }
+
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+ bool setSuccessfully = TrySetResult(true);
+ Debug.Assert(setSuccessfully, "Should have been able to complete task");
+ }
+#if CORECLR
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ }
+#endif
+ }
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Gets the current count of the <see cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <value>The current count of the <see cref="SemaphoreSlim"/>.</value>
+ public int CurrentCount
+ {
+ get { return m_currentCount; }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="T:System.Threading.WaitHandle"/> that can be used to wait on the semaphore.
+ /// </summary>
+ /// <value>A <see cref="T:System.Threading.WaitHandle"/> that can be used to wait on the
+ /// semaphore.</value>
+ /// <remarks>
+ /// A successful wait on the <see cref="AvailableWaitHandle"/> does not imply a successful wait on
+ /// the <see cref="SemaphoreSlim"/> itself, nor does it decrement the semaphore's
+ /// count. <see cref="AvailableWaitHandle"/> exists to allow a thread to block waiting on multiple
+ /// semaphores, but such a wait should be followed by a true wait on the target semaphore.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The <see
+ /// cref="SemaphoreSlim"/> has been disposed.</exception>
+ public WaitHandle AvailableWaitHandle
+ {
+ get
+ {
+ CheckDispose();
+
+ // Return it directly if it is not null
+ if (m_waitHandle != null)
+ return m_waitHandle;
+
+ //lock the count to avoid multiple threads initializing the handle if it is null
+ lock (m_lockObj)
+ {
+ if (m_waitHandle == null)
+ {
+ // The initial state for the wait handle is true if the count is greater than zero
+ // false otherwise
+ m_waitHandle = new ManualResetEvent(m_currentCount != 0);
+ }
+ }
+ return m_waitHandle;
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SemaphoreSlim"/> class, specifying
+ /// the initial number of requests that can be granted concurrently.
+ /// </summary>
+ /// <param name="initialCount">The initial number of requests for the semaphore that can be granted
+ /// concurrently.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="initialCount"/>
+ /// is less than 0.</exception>
+ public SemaphoreSlim(int initialCount)
+ : this(initialCount, NO_MAXIMUM)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SemaphoreSlim"/> class, specifying
+ /// the initial and maximum number of requests that can be granted concurrently.
+ /// </summary>
+ /// <param name="initialCount">The initial number of requests for the semaphore that can be granted
+ /// concurrently.</param>
+ /// <param name="maxCount">The maximum number of requests for the semaphore that can be granted
+ /// concurrently.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> <paramref name="initialCount"/>
+ /// is less than 0. -or-
+ /// <paramref name="initialCount"/> is greater than <paramref name="maxCount"/>. -or-
+ /// <paramref name="maxCount"/> is less than 0.</exception>
+ public SemaphoreSlim(int initialCount, int maxCount)
+ {
+ if (initialCount < 0 || initialCount > maxCount)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(initialCount), initialCount, SR.SemaphoreSlim_ctor_InitialCountWrong);
+ }
+
+ //validate input
+ if (maxCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(maxCount), maxCount, SR.SemaphoreSlim_ctor_MaxCountWrong);
+ }
+
+ m_maxCount = maxCount;
+ m_lockObj = new object();
+ m_currentCount = initialCount;
+ }
+
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void Wait()
+ {
+ // Call wait with infinite timeout
+ Wait(Timeout.Infinite, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> token to
+ /// observe.</param>
+ /// <exception cref="T:System.OperationCanceledException"><paramref name="cancellationToken"/> was
+ /// canceled.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ // Call wait with infinite timeout
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ // Validate the timeout
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
+ }
+
+ // Call wait with the timeout milliseconds
+ return Wait((int)timeout.TotalMilliseconds, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ // Validate the timeout
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
+ }
+
+ // Call wait with the timeout milliseconds
+ return Wait((int)timeout.TotalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, using a 32-bit
+ /// signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, new CancellationToken());
+ }
+
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>,
+ /// using a 32-bit signed integer to measure the time interval,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to
+ /// wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
+ /// which represents an infinite time-out.</exception>
+ /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ CheckDispose();
+
+ // Validate input
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(millisecondsTimeout), millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // Perf: Check the stack timeout parameter before checking the volatile count
+ if (millisecondsTimeout == 0 && m_currentCount == 0)
+ {
+ // Pessimistic fail fast, check volatile count outside lock (only when timeout is zero!)
+ return false;
+ }
+
+ uint startTime = 0;
+ if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
+ {
+ startTime = TimeoutHelper.GetTime();
+ }
+
+ bool waitSuccessful = false;
+ Task<bool> asyncWaitTask = null;
+ bool lockTaken = false;
+
+ //Register for cancellation outside of the main lock.
+ //NOTE: Register/unregister inside the lock can deadlock as different lock acquisition orders could
+ // occur for (1)this.m_lockObj and (2)cts.internalLock
+ CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this);
+ try
+ {
+ // Perf: first spin wait for the count to be positive.
+ // This additional amount of spinwaiting in addition
+ // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
+ if (m_currentCount == 0)
+ {
+ // Monitor.Enter followed by Monitor.Wait is much more expensive than waiting on an event as it involves another
+ // spin, contention, etc. The usual number of spin iterations that would otherwise be used here is increased to
+ // lessen that extra expense of doing a proper wait.
+ int spinCount = SpinWait.SpinCountforSpinBeforeWait * 4;
+
+ var spinner = new SpinWait();
+ while (spinner.Count < spinCount)
+ {
+ spinner.SpinOnce(sleep1Threshold: -1);
+
+ if (m_currentCount != 0)
+ {
+ break;
+ }
+ }
+ }
+ // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
+ // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
+ try { }
+ finally
+ {
+ Monitor.Enter(m_lockObj, ref lockTaken);
+ if (lockTaken)
+ {
+ m_waitCount++;
+ }
+ }
+
+ // If there are any async waiters, for fairness we'll get in line behind
+ // then by translating our synchronous wait into an asynchronous one that we
+ // then block on (once we've released the lock).
+ if (m_asyncHead != null)
+ {
+ Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't");
+ asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
+ }
+ // There are no async waiters, so we can proceed with normal synchronous waiting.
+ else
+ {
+ // If the count > 0 we are good to move on.
+ // If not, then wait if we were given allowed some wait duration
+
+ OperationCanceledException oce = null;
+
+ if (m_currentCount == 0)
+ {
+ if (millisecondsTimeout == 0)
+ {
+ return false;
+ }
+
+ // Prepare for the main wait...
+ // wait until the count become greater than zero or the timeout is expired
+ try
+ {
+ waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
+ }
+ catch (OperationCanceledException e) { oce = e; }
+ }
+
+ // Now try to acquire. We prioritize acquisition over cancellation/timeout so that we don't
+ // lose any counts when there are asynchronous waiters in the mix. Asynchronous waiters
+ // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
+ // waiter didn't get released because a synchronous waiter was present, we need to ensure
+ // that synchronous waiter succeeds so that they have a chance to release.
+ Debug.Assert(!waitSuccessful || m_currentCount > 0,
+ "If the wait was successful, there should be count available.");
+ if (m_currentCount > 0)
+ {
+ waitSuccessful = true;
+ m_currentCount--;
+ }
+ else if (oce != null)
+ {
+ throw oce;
+ }
+
+ // Exposing wait handle which is lazily initialized if needed
+ if (m_waitHandle != null && m_currentCount == 0)
+ {
+ m_waitHandle.Reset();
+ }
+ }
+ }
+ finally
+ {
+ // Release the lock
+ if (lockTaken)
+ {
+ m_waitCount--;
+ Monitor.Exit(m_lockObj);
+ }
+
+ // Unregister the cancellation callback.
+ cancellationTokenRegistration.Dispose();
+ }
+
+ // If we had to fall back to asynchronous waiting, block on it
+ // here now that we've released the lock, and return its
+ // result when available. Otherwise, this was a synchronous
+ // wait, and whether we successfully acquired the semaphore is
+ // stored in waitSuccessful.
+
+ return (asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful;
+ }
+
+ /// <summary>
+ /// Local helper function, waits on the monitor until the monitor receives signal or the
+ /// timeout is expired
+ /// </summary>
+ /// <param name="millisecondsTimeout">The maximum timeout</param>
+ /// <param name="startTime">The start ticks to calculate the elapsed time</param>
+ /// <param name="cancellationToken">The CancellationToken to observe.</param>
+ /// <returns>true if the monitor received a signal, false if the timeout expired</returns>
+ private bool WaitUntilCountOrTimeout(int millisecondsTimeout, uint startTime, CancellationToken cancellationToken)
+ {
+ int remainingWaitMilliseconds = Timeout.Infinite;
+
+ //Wait on the monitor as long as the count is zero
+ while (m_currentCount == 0)
+ {
+ // If cancelled, we throw. Trying to wait could lead to deadlock.
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (millisecondsTimeout != Timeout.Infinite)
+ {
+ remainingWaitMilliseconds = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
+ if (remainingWaitMilliseconds <= 0)
+ {
+ // The thread has expires its timeout
+ return false;
+ }
+ }
+ // ** the actual wait **
+ bool waitSuccessful = Monitor.Wait(m_lockObj, remainingWaitMilliseconds);
+
+ // This waiter has woken up and this needs to be reflected in the count of waiters pulsed to wake. Since we
+ // don't have thread-specific pulse state, there is not enough information to tell whether this thread woke up
+ // because it was pulsed. For instance, this thread may have timed out and may have been waiting to reacquire
+ // the lock before returning from Monitor.Wait, in which case we don't know whether this thread got pulsed. So
+ // in any woken case, decrement the count if possible. As such, timeouts could cause more waiters to wake than
+ // necessary.
+ if (m_countOfWaitersPulsedToWake != 0)
+ {
+ --m_countOfWaitersPulsedToWake;
+ }
+
+ if (!waitSuccessful)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <returns>A task that will complete when the semaphore has been entered.</returns>
+ public Task WaitAsync()
+ {
+ return WaitAsync(Timeout.Infinite, default);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <returns>A task that will complete when the semaphore has been entered.</returns>
+ /// <param name="cancellationToken">
+ /// The <see cref="T:System.Threading.CancellationToken"/> token to observe.
+ /// </param>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The current instance has already been disposed.
+ /// </exception>
+ public Task WaitAsync(CancellationToken cancellationToken)
+ {
+ return WaitAsync(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>,
+ /// using a 32-bit signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
+ /// which represents an infinite time-out.
+ /// </exception>
+ public Task<bool> WaitAsync(int millisecondsTimeout)
+ {
+ return WaitAsync(millisecondsTimeout, default);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// The <see cref="T:System.Threading.CancellationToken"/> token to observe.
+ /// </param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The current instance has already been disposed.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
+ /// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ public Task<bool> WaitAsync(TimeSpan timeout)
+ {
+ return WaitAsync(timeout, default);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
+ /// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ public Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ // Validate the timeout
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
+ }
+
+ // Call wait with the timeout milliseconds
+ return WaitAsync((int)timeout.TotalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>,
+ /// using a 32-bit signed integer to measure the time interval,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
+ /// which represents an infinite time-out.
+ /// </exception>
+ public Task<bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ CheckDispose();
+
+ // Validate input
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(millisecondsTimeout), millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
+ }
+
+ // Bail early for cancellation
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<bool>(cancellationToken);
+
+ lock (m_lockObj)
+ {
+ // If there are counts available, allow this waiter to succeed.
+ if (m_currentCount > 0)
+ {
+ --m_currentCount;
+ if (m_waitHandle != null && m_currentCount == 0) m_waitHandle.Reset();
+ return s_trueTask;
+ }
+ else if (millisecondsTimeout == 0)
+ {
+ // No counts, if timeout is zero fail fast
+ return s_falseTask;
+ }
+ // If there aren't, create and return a task to the caller.
+ // The task will be completed either when they've successfully acquired
+ // the semaphore or when the timeout expired or cancellation was requested.
+ else
+ {
+ Debug.Assert(m_currentCount == 0, "m_currentCount should never be negative");
+ var asyncWaiter = CreateAndAddAsyncWaiter();
+ return (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled) ?
+ asyncWaiter :
+ WaitUntilCountOrTimeoutAsync(asyncWaiter, millisecondsTimeout, cancellationToken);
+ }
+ }
+ }
+
+ /// <summary>Creates a new task and stores it into the async waiters list.</summary>
+ /// <returns>The created task.</returns>
+ private TaskNode CreateAndAddAsyncWaiter()
+ {
+ Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
+
+ // Create the task
+ var task = new TaskNode();
+
+ // Add it to the linked list
+ if (m_asyncHead == null)
+ {
+ Debug.Assert(m_asyncTail == null, "If head is null, so too should be tail");
+ m_asyncHead = task;
+ m_asyncTail = task;
+ }
+ else
+ {
+ Debug.Assert(m_asyncTail != null, "If head is not null, neither should be tail");
+ m_asyncTail.Next = task;
+ task.Prev = m_asyncTail;
+ m_asyncTail = task;
+ }
+
+ // Hand it back
+ return task;
+ }
+
+ /// <summary>Removes the waiter task from the linked list.</summary>
+ /// <param name="task">The task to remove.</param>
+ /// <returns>true if the waiter was in the list; otherwise, false.</returns>
+ private bool RemoveAsyncWaiter(TaskNode task)
+ {
+ Debug.Assert(task != null, "Expected non-null task");
+ Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
+
+ // Is the task in the list? To be in the list, either it's the head or it has a predecessor that's in the list.
+ bool wasInList = m_asyncHead == task || task.Prev != null;
+
+ // Remove it from the linked list
+ if (task.Next != null) task.Next.Prev = task.Prev;
+ if (task.Prev != null) task.Prev.Next = task.Next;
+ if (m_asyncHead == task) m_asyncHead = task.Next;
+ if (m_asyncTail == task) m_asyncTail = task.Prev;
+ Debug.Assert((m_asyncHead == null) == (m_asyncTail == null), "Head is null iff tail is null");
+
+ // Make sure not to leak
+ task.Next = task.Prev = null;
+
+ // Return whether the task was in the list
+ return wasInList;
+ }
+
+ /// <summary>Performs the asynchronous wait.</summary>
+ /// <param name="millisecondsTimeout">The timeout.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>The task to return to the caller.</returns>
+ private async Task<bool> WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ Debug.Assert(asyncWaiter != null, "Waiter should have been constructed");
+ Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
+
+ // Wait until either the task is completed, timeout occurs, or cancellation is requested.
+ // We need to ensure that the Task.Delay task is appropriately cleaned up if the await
+ // completes due to the asyncWaiter completing, so we use our own token that we can explicitly
+ // cancel, and we chain the caller's supplied token into it.
+ using (var cts = cancellationToken.CanBeCanceled ?
+ CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default) :
+ new CancellationTokenSource())
+ {
+ var waitCompleted = Task.WhenAny(asyncWaiter, Task.Delay(millisecondsTimeout, cts.Token));
+ if (asyncWaiter == await waitCompleted.ConfigureAwait(false))
+ {
+ cts.Cancel(); // ensure that the Task.Delay task is cleaned up
+ return true; // successfully acquired
+ }
+ }
+
+ // If we get here, the wait has timed out or been canceled.
+
+ // If the await completed synchronously, we still hold the lock. If it didn't,
+ // we no longer hold the lock. As such, acquire it.
+ lock (m_lockObj)
+ {
+ // Remove the task from the list. If we're successful in doing so,
+ // we know that no one else has tried to complete this waiter yet,
+ // so we can safely cancel or timeout.
+ if (RemoveAsyncWaiter(asyncWaiter))
+ {
+ cancellationToken.ThrowIfCancellationRequested(); // cancellation occurred
+ return false; // timeout occurred
+ }
+ }
+
+ // The waiter had already been removed, which means it's already completed or is about to
+ // complete, so let it, and don't return until it does.
+ return await asyncWaiter.ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Exits the <see cref="SemaphoreSlim"/> once.
+ /// </summary>
+ /// <returns>The previous count of the <see cref="SemaphoreSlim"/>.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public int Release()
+ {
+ return Release(1);
+ }
+
+ /// <summary>
+ /// Exits the <see cref="SemaphoreSlim"/> a specified number of times.
+ /// </summary>
+ /// <param name="releaseCount">The number of times to exit the semaphore.</param>
+ /// <returns>The previous count of the <see cref="SemaphoreSlim"/>.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="releaseCount"/> is less
+ /// than 1.</exception>
+ /// <exception cref="T:System.Threading.SemaphoreFullException">The <see cref="SemaphoreSlim"/> has
+ /// already reached its maximum size.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public int Release(int releaseCount)
+ {
+ CheckDispose();
+
+ // Validate input
+ if (releaseCount < 1)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(releaseCount), releaseCount, SR.SemaphoreSlim_Release_CountWrong);
+ }
+ int returnCount;
+
+ lock (m_lockObj)
+ {
+ // Read the m_currentCount into a local variable to avoid unnecessary volatile accesses inside the lock.
+ int currentCount = m_currentCount;
+ returnCount = currentCount;
+
+ // If the release count would result exceeding the maximum count, throw SemaphoreFullException.
+ if (m_maxCount - currentCount < releaseCount)
+ {
+ throw new SemaphoreFullException();
+ }
+
+ // Increment the count by the actual release count
+ currentCount += releaseCount;
+
+ // Signal to any synchronous waiters, taking into account how many waiters have previously been pulsed to wake
+ // but have not yet woken
+ int waitCount = m_waitCount;
+ Debug.Assert(m_countOfWaitersPulsedToWake <= waitCount);
+ int waitersToNotify = Math.Min(currentCount, waitCount) - m_countOfWaitersPulsedToWake;
+ if (waitersToNotify > 0)
+ {
+ // Ideally, limiting to a maximum of releaseCount would not be necessary and could be an assert instead, but
+ // since WaitUntilCountOrTimeout() does not have enough information to tell whether a woken thread was
+ // pulsed, it's possible for m_countOfWaitersPulsedToWake to be less than the number of threads that have
+ // actually been pulsed to wake.
+ if (waitersToNotify > releaseCount)
+ {
+ waitersToNotify = releaseCount;
+ }
+
+ m_countOfWaitersPulsedToWake += waitersToNotify;
+ for (int i = 0; i < waitersToNotify; i++)
+ {
+ Monitor.Pulse(m_lockObj);
+ }
+ }
+
+ // Now signal to any asynchronous waiters, if there are any. While we've already
+ // signaled the synchronous waiters, we still hold the lock, and thus
+ // they won't have had an opportunity to acquire this yet. So, when releasing
+ // asynchronous waiters, we assume that all synchronous waiters will eventually
+ // acquire the semaphore. That could be a faulty assumption if those synchronous
+ // waits are canceled, but the wait code path will handle that.
+ if (m_asyncHead != null)
+ {
+ Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't null");
+ int maxAsyncToRelease = currentCount - waitCount;
+ while (maxAsyncToRelease > 0 && m_asyncHead != null)
+ {
+ --currentCount;
+ --maxAsyncToRelease;
+
+ // Get the next async waiter to release and queue it to be completed
+ var waiterTask = m_asyncHead;
+ RemoveAsyncWaiter(waiterTask); // ensures waiterTask.Next/Prev are null
+ QueueWaiterTask(waiterTask);
+ }
+ }
+ m_currentCount = currentCount;
+
+ // Exposing wait handle if it is not null
+ if (m_waitHandle != null && returnCount == 0 && currentCount > 0)
+ {
+ m_waitHandle.Set();
+ }
+ }
+
+ // And return the count
+ return returnCount;
+ }
+
+ /// <summary>
+ /// Queues a waiter task to the ThreadPool. We use this small helper method so that
+ /// the larger Release(count) method does not need to be SecuritySafeCritical.
+ /// </summary>
+ private static void QueueWaiterTask(TaskNode waiterTask)
+ {
+ ThreadPool.UnsafeQueueCustomWorkItem(waiterTask, forceGlobal: false);
+ }
+
+ /// <summary>
+ /// Releases all resources used by the current instance of <see
+ /// cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="SemaphoreSlim"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// <see cref="T:System.Threading.ManualResetEventSlim"/>, and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="SemaphoreSlim"/>, <see cref="Dispose(bool)"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (m_waitHandle != null)
+ {
+ m_waitHandle.Dispose();
+ m_waitHandle = null;
+ }
+ m_lockObj = null;
+ m_asyncHead = null;
+ m_asyncTail = null;
+ }
+ }
+
+ /// <summary>
+ /// Private helper method to wake up waiters when a cancellationToken gets canceled.
+ /// </summary>
+ private static Action<object> s_cancellationTokenCanceledEventHandler = new Action<object>(CancellationTokenCanceledEventHandler);
+ private static void CancellationTokenCanceledEventHandler(object obj)
+ {
+ SemaphoreSlim semaphore = obj as SemaphoreSlim;
+ Debug.Assert(semaphore != null, "Expected a SemaphoreSlim");
+ lock (semaphore.m_lockObj)
+ {
+ Monitor.PulseAll(semaphore.m_lockObj); //wake up all waiters.
+ }
+ }
+
+ /// <summary>
+ /// Checks the dispose status by checking the lock object, if it is null means that object
+ /// has been disposed and throw ObjectDisposedException
+ /// </summary>
+ private void CheckDispose()
+ {
+ if (m_lockObj == null)
+ {
+ throw new ObjectDisposedException(null, SR.SemaphoreSlim_Disposed);
+ }
+ }
+ #endregion
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs b/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs
index 6692d35ab..b96914ab2 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs
@@ -4,5 +4,5 @@
namespace System.Threading
{
- public delegate void SendOrPostCallback(Object state);
+ public delegate void SendOrPostCallback(object state);
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs b/src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs
new file mode 100644
index 000000000..2b0610539
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs
@@ -0,0 +1,650 @@
+// 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.
+#pragma warning disable 0420
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// A spin lock is a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop ("spins")
+// repeatedly checking until the lock becomes available. As the thread remains active performing a non-useful task,
+// the use of such a lock is a kind of busy waiting and consumes CPU resources without performing real work.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Provides a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop
+ /// repeatedly checking until the lock becomes available.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Spin locks can be used for leaf-level locks where the object allocation implied by using a <see
+ /// cref="System.Threading.Monitor"/>, in size or due to garbage collection pressure, is overly
+ /// expensive. Avoiding blocking is another reason that a spin lock can be useful, however if you expect
+ /// any significant amount of blocking, you are probably best not using spin locks due to excessive
+ /// spinning. Spinning can be beneficial when locks are fine grained and large in number (for example, a
+ /// lock per node in a linked list) as well as when lock hold times are always extremely short. In
+ /// general, while holding a spin lock, one should avoid blocking, calling anything that itself may
+ /// block, holding more than one spin lock at once, making dynamically dispatched calls (interface and
+ /// virtuals), making statically dispatched calls into any code one doesn't own, or allocating memory.
+ /// </para>
+ /// <para>
+ /// <see cref="SpinLock"/> should only be used when it's been determined that doing so will improve an
+ /// application's performance. It's also important to note that <see cref="SpinLock"/> is a value type,
+ /// for performance reasons. As such, one must be very careful not to accidentally copy a SpinLock
+ /// instance, as the two instances (the original and the copy) would then be completely independent of
+ /// one another, which would likely lead to erroneous behavior of the application. If a SpinLock instance
+ /// must be passed around, it should be passed by reference rather than by value.
+ /// </para>
+ /// <para>
+ /// Do not store <see cref="SpinLock"/> instances in readonly fields.
+ /// </para>
+ /// <para>
+ /// All members of <see cref="SpinLock"/> are thread-safe and may be used from multiple threads
+ /// concurrently.
+ /// </para>
+ /// </remarks>
+ [DebuggerTypeProxy(typeof(SystemThreading_SpinLockDebugView))]
+ [DebuggerDisplay("IsHeld = {IsHeld}")]
+ public struct SpinLock
+ {
+ // The current ownership state is a single signed int. There are two modes:
+ //
+ // 1) Ownership tracking enabled: the high bit is 0, and the remaining bits
+ // store the managed thread ID of the current owner. When the 31 low bits
+ // are 0, the lock is available.
+ // 2) Performance mode: when the high bit is 1, lock availability is indicated by the low bit.
+ // When the low bit is 1 -- the lock is held; 0 -- the lock is available.
+ //
+ // There are several masks and constants below for convenience.
+
+ private volatile int _owner;
+
+ // After how many yields, call Sleep(1)
+ private const int SLEEP_ONE_FREQUENCY = 40;
+
+ // After how many yields, check the timeout
+ private const int TIMEOUT_CHECK_FREQUENCY = 10;
+
+ // Thr thread tracking disabled mask
+ private const int LOCK_ID_DISABLE_MASK = unchecked((int)0x80000000); // 1000 0000 0000 0000 0000 0000 0000 0000
+
+ //the lock is held by some thread, but we don't know which
+ private const int LOCK_ANONYMOUS_OWNED = 0x1; // 0000 0000 0000 0000 0000 0000 0000 0001
+
+ // Waiters mask if the thread tracking is disabled
+ private const int WAITERS_MASK = ~(LOCK_ID_DISABLE_MASK | 1); // 0111 1111 1111 1111 1111 1111 1111 1110
+
+ // The Thread tacking is disabled and the lock bit is set, used in Enter fast path to make sure the id is disabled and lock is available
+ private const int ID_DISABLED_AND_ANONYMOUS_OWNED = unchecked((int)0x80000001); // 1000 0000 0000 0000 0000 0000 0000 0001
+
+ // If the thread is unowned if:
+ // m_owner zero and the thread tracking is enabled
+ // m_owner & LOCK_ANONYMOUS_OWNED = zero and the thread tracking is disabled
+ private const int LOCK_UNOWNED = 0;
+
+ // The maximum number of waiters (only used if the thread tracking is disabled)
+ // The actual maximum waiters count is this number divided by two because each waiter increments the waiters count by 2
+ // The waiters count is calculated by m_owner & WAITERS_MASK 01111....110
+ private static int MAXIMUM_WAITERS = WAITERS_MASK;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int CompareExchange(ref int location, int value, int comparand, ref bool success)
+ {
+ int result = Interlocked.CompareExchange(ref location, value, comparand);
+ success = (result == comparand);
+ return result;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/>
+ /// structure with the option to track thread IDs to improve debugging.
+ /// </summary>
+ /// <remarks>
+ /// The default constructor for <see cref="SpinLock"/> tracks thread ownership.
+ /// </remarks>
+ /// <param name="enableThreadOwnerTracking">Whether to capture and use thread IDs for debugging
+ /// purposes.</param>
+ public SpinLock(bool enableThreadOwnerTracking)
+ {
+ _owner = LOCK_UNOWNED;
+ if (!enableThreadOwnerTracking)
+ {
+ _owner |= LOCK_ID_DISABLE_MASK;
+ Debug.Assert(!IsThreadOwnerTrackingEnabled, "property should be false by now");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/>
+ /// structure with the option to track thread IDs to improve debugging.
+ /// </summary>
+ /// <remarks>
+ /// The default constructor for <see cref="SpinLock"/> tracks thread ownership.
+ /// </remarks>
+ /// <summary>
+ /// Acquires the lock in a reliable manner, such that even if an exception occurs within the method
+ /// call, <paramref name="lockTaken"/> can be examined reliably to determine whether the lock was
+ /// acquired.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="SpinLock"/> is a non-reentrant lock, meaning that if a thread holds the lock, it is
+ /// not allowed to enter the lock again. If thread ownership tracking is enabled (whether it's
+ /// enabled is available through <see cref="IsThreadOwnerTrackingEnabled"/>), an exception will be
+ /// thrown when a thread tries to re-enter a lock it already holds. However, if thread ownership
+ /// tracking is disabled, attempting to enter a lock already held will result in deadlock.
+ /// </remarks>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling Enter.
+ /// </exception>
+ public void Enter(ref bool lockTaken)
+ {
+ // Try to keep the code and branching in this method as small as possible in order to inline the method
+ int observedOwner = _owner;
+ if (lockTaken || // invalid parameter
+ (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || // thread tracking is enabled or the lock is already acquired
+ CompareExchange(ref _owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) //acquiring the lock failed
+ ContinueTryEnter(Timeout.Infinite, ref lockTaken); // Then try the slow path if any of the above conditions is met
+ }
+
+ /// <summary>
+ /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within
+ /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the
+ /// lock was acquired.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="Enter"/>, TryEnter will not block waiting for the lock to be available. If the
+ /// lock is not available when TryEnter is called, it will return immediately without any further
+ /// spinning.
+ /// </remarks>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter.
+ /// </exception>
+ public void TryEnter(ref bool lockTaken)
+ {
+ int observedOwner = _owner;
+ if (((observedOwner & LOCK_ID_DISABLE_MASK) == 0) | lockTaken)
+ {
+ // Thread tracking enabled or invalid arg. Take slow path.
+ ContinueTryEnter(0, ref lockTaken);
+ }
+ else if ((observedOwner & LOCK_ANONYMOUS_OWNED) != 0)
+ {
+ // Lock already held by someone
+ lockTaken = false;
+ }
+ else
+ {
+ // Lock wasn't held; try to acquire it.
+ CompareExchange(ref _owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken);
+ }
+ }
+
+ /// <summary>
+ /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within
+ /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the
+ /// lock was acquired.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="Enter"/>, TryEnter will not block indefinitely waiting for the lock to be
+ /// available. It will block until either the lock is available or until the <paramref
+ /// name="timeout"/>
+ /// has expired.
+ /// </remarks>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/> milliseconds.
+ /// </exception>
+ public void TryEnter(TimeSpan timeout, ref bool lockTaken)
+ {
+ // Validate the timeout
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ nameof(timeout), timeout, SR.SpinLock_TryEnter_ArgumentOutOfRange);
+ }
+
+ // Call reliable enter with the int-based timeout milliseconds
+ TryEnter((int)timeout.TotalMilliseconds, ref lockTaken);
+ }
+
+ /// <summary>
+ /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within
+ /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the
+ /// lock was acquired.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="Enter"/>, TryEnter will not block indefinitely waiting for the lock to be
+ /// available. It will block until either the lock is available or until the <paramref
+ /// name="millisecondsTimeout"/> has expired.
+ /// </remarks>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is
+ /// a negative number other than -1, which represents an infinite time-out.</exception>
+ public void TryEnter(int millisecondsTimeout, ref bool lockTaken)
+ {
+ int observedOwner = _owner;
+ if (millisecondsTimeout < -1 || //invalid parameter
+ lockTaken || //invalid parameter
+ (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || //thread tracking is enabled or the lock is already acquired
+ CompareExchange(ref _owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) // acquiring the lock failed
+ ContinueTryEnter(millisecondsTimeout, ref lockTaken); // The call the slow pth
+ }
+
+ /// <summary>
+ /// Try acquire the lock with long path, this is usually called after the first path in Enter and
+ /// TryEnter failed The reason for short path is to make it inline in the run time which improves the
+ /// performance. This method assumed that the parameter are validated in Enter or TryEnter method.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The timeout milliseconds</param>
+ /// <param name="lockTaken">The lockTaken param</param>
+ private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken)
+ {
+ // The fast path doesn't throw any exception, so we have to validate the parameters here
+ if (lockTaken)
+ {
+ lockTaken = false;
+ throw new ArgumentException(SR.SpinLock_TryReliableEnter_ArgumentException);
+ }
+
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(millisecondsTimeout), millisecondsTimeout, SR.SpinLock_TryEnter_ArgumentOutOfRange);
+ }
+
+ uint startTime = 0;
+ if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout != 0)
+ {
+ startTime = TimeoutHelper.GetTime();
+ }
+
+ if (IsThreadOwnerTrackingEnabled)
+ {
+ // Slow path for enabled thread tracking mode
+ ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTime, ref lockTaken);
+ return;
+ }
+
+ // then thread tracking is disabled
+ // In this case there are three ways to acquire the lock
+ // 1- the first way the thread either tries to get the lock if it's free or updates the waiters, if the turn >= the processors count then go to 3 else go to 2
+ // 2- In this step the waiter threads spins and tries to acquire the lock, the number of spin iterations and spin count is dependent on the thread turn
+ // the late the thread arrives the more it spins and less frequent it check the lock availability
+ // Also the spins count is increases each iteration
+ // If the spins iterations finished and failed to acquire the lock, go to step 3
+ // 3- This is the yielding step, there are two ways of yielding Thread.Yield and Sleep(1)
+ // If the timeout is expired in after step 1, we need to decrement the waiters count before returning
+
+ int observedOwner;
+ int turn = int.MaxValue;
+ //***Step 1, take the lock or update the waiters
+
+ // try to acquire the lock directly if possible or update the waiters count
+ observedOwner = _owner;
+ if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
+ {
+ if (CompareExchange(ref _owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner)
+ {
+ // Acquired lock
+ return;
+ }
+
+ if (millisecondsTimeout == 0)
+ {
+ // Did not acquire lock in CompareExchange and timeout is 0 so fail fast
+ return;
+ }
+ }
+ else if (millisecondsTimeout == 0)
+ {
+ // Did not acquire lock as owned and timeout is 0 so fail fast
+ return;
+ }
+ else //failed to acquire the lock, then try to update the waiters. If the waiters count reached the maximum, just break the loop to avoid overflow
+ {
+ if ((observedOwner & WAITERS_MASK) != MAXIMUM_WAITERS)
+ {
+ // This can still overflow, but maybe there will never be that many waiters
+ turn = (Interlocked.Add(ref _owner, 2) & WAITERS_MASK) >> 1;
+ }
+ }
+
+ // lock acquired failed and waiters updated
+
+ //*** Step 2, Spinning and Yielding
+ var spinner = new SpinWait();
+ if (turn > PlatformHelper.ProcessorCount)
+ {
+ spinner.Count = SpinWait.YieldThreshold;
+ }
+ while (true)
+ {
+ spinner.SpinOnce(SLEEP_ONE_FREQUENCY);
+
+ observedOwner = _owner;
+ if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
+ {
+ int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero
+ observedOwner | 1 // don't decrement it. just set the lock bit, it is zero because a previous call of Exit(false) which corrupted the waiters
+ : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
+ Debug.Assert((newOwner & WAITERS_MASK) >= 0);
+
+ if (CompareExchange(ref _owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
+ {
+ return;
+ }
+ }
+
+ if (spinner.Count % TIMEOUT_CHECK_FREQUENCY == 0)
+ {
+ // Check the timeout.
+ if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)
+ {
+ DecrementWaiters();
+ return;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// decrements the waiters, in case of the timeout is expired
+ /// </summary>
+ private void DecrementWaiters()
+ {
+ SpinWait spinner = new SpinWait();
+ while (true)
+ {
+ int observedOwner = _owner;
+ if ((observedOwner & WAITERS_MASK) == 0) return; // don't decrement the waiters if it's corrupted by previous call of Exit(false)
+ if (Interlocked.CompareExchange(ref _owner, observedOwner - 2, observedOwner) == observedOwner)
+ {
+ Debug.Assert(!IsThreadOwnerTrackingEnabled); // Make sure the waiters never be negative which will cause the thread tracking bit to be flipped
+ break;
+ }
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>
+ /// ContinueTryEnter for the thread tracking mode enabled
+ /// </summary>
+ private void ContinueTryEnterWithThreadTracking(int millisecondsTimeout, uint startTime, ref bool lockTaken)
+ {
+ Debug.Assert(IsThreadOwnerTrackingEnabled);
+
+ int lockUnowned = 0;
+ // We are using thread IDs to mark ownership. Snap the thread ID and check for recursion.
+ // We also must or the ID enablement bit, to ensure we propagate when we CAS it in.
+ int newOwner = Environment.CurrentManagedThreadId;
+ if (_owner == newOwner)
+ {
+ // We don't allow lock recursion.
+ throw new LockRecursionException(SR.SpinLock_TryEnter_LockRecursionException);
+ }
+
+
+ SpinWait spinner = new SpinWait();
+
+ // Loop until the lock has been successfully acquired or, if specified, the timeout expires.
+ do
+ {
+ // We failed to get the lock, either from the fast route or the last iteration
+ // and the timeout hasn't expired; spin once and try again.
+ spinner.SpinOnce();
+
+ // Test before trying to CAS, to avoid acquiring the line exclusively unnecessarily.
+
+ if (_owner == lockUnowned)
+ {
+ if (CompareExchange(ref _owner, newOwner, lockUnowned, ref lockTaken) == lockUnowned)
+ {
+ return;
+ }
+ }
+ // Check the timeout. We only RDTSC if the next spin will yield, to amortize the cost.
+ if (millisecondsTimeout == 0 ||
+ (millisecondsTimeout != Timeout.Infinite && spinner.NextSpinWillYield &&
+ TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0))
+ {
+ return;
+ }
+ } while (true);
+ }
+
+ /// <summary>
+ /// Releases the lock.
+ /// </summary>
+ /// <remarks>
+ /// The default overload of <see cref="Exit()"/> provides the same behavior as if calling <see
+ /// cref="Exit(bool)"/> using true as the argument, but Exit() could be slightly faster than Exit(true).
+ /// </remarks>
+ /// <exception cref="SynchronizationLockException">
+ /// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
+ /// </exception>
+ public void Exit()
+ {
+ //This is the fast path for the thread tracking is disabled, otherwise go to the slow path
+ if ((_owner & LOCK_ID_DISABLE_MASK) == 0)
+ ExitSlowPath(true);
+ else
+ Interlocked.Decrement(ref _owner);
+ }
+
+ /// <summary>
+ /// Releases the lock.
+ /// </summary>
+ /// <param name="useMemoryBarrier">
+ /// A Boolean value that indicates whether a memory fence should be issued in order to immediately
+ /// publish the exit operation to other threads.
+ /// </param>
+ /// <remarks>
+ /// Calling <see cref="Exit(bool)"/> with the <paramref name="useMemoryBarrier"/> argument set to
+ /// true will improve the fairness of the lock at the expense of some performance. The default <see
+ /// cref="Enter"/>
+ /// overload behaves as if specifying true for <paramref name="useMemoryBarrier"/>.
+ /// </remarks>
+ /// <exception cref="SynchronizationLockException">
+ /// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
+ /// </exception>
+ public void Exit(bool useMemoryBarrier)
+ {
+ // This is the fast path for the thread tracking is disabled and not to use memory barrier, otherwise go to the slow path
+ // The reason not to add else statement if the usememorybarrier is that it will add more branching in the code and will prevent
+ // method inlining, so this is optimized for useMemoryBarrier=false and Exit() overload optimized for useMemoryBarrier=true.
+ int tmpOwner = _owner;
+ if ((tmpOwner & LOCK_ID_DISABLE_MASK) != 0 & !useMemoryBarrier)
+ {
+ _owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
+ }
+ else
+ {
+ ExitSlowPath(useMemoryBarrier);
+ }
+ }
+
+ /// <summary>
+ /// The slow path for exit method if the fast path failed
+ /// </summary>
+ /// <param name="useMemoryBarrier">
+ /// A Boolean value that indicates whether a memory fence should be issued in order to immediately
+ /// publish the exit operation to other threads
+ /// </param>
+ private void ExitSlowPath(bool useMemoryBarrier)
+ {
+ bool threadTrackingEnabled = (_owner & LOCK_ID_DISABLE_MASK) == 0;
+ if (threadTrackingEnabled && !IsHeldByCurrentThread)
+ {
+ throw new SynchronizationLockException(SR.SpinLock_Exit_SynchronizationLockException);
+ }
+
+ if (useMemoryBarrier)
+ {
+ if (threadTrackingEnabled)
+ {
+ Interlocked.Exchange(ref _owner, LOCK_UNOWNED);
+ }
+ else
+ {
+ Interlocked.Decrement(ref _owner);
+ }
+ }
+ else
+ {
+ if (threadTrackingEnabled)
+ {
+ _owner = LOCK_UNOWNED;
+ }
+ else
+ {
+ int tmpOwner = _owner;
+ _owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the lock is currently held by any thread.
+ /// </summary>
+ public bool IsHeld
+ {
+ get
+ {
+ if (IsThreadOwnerTrackingEnabled)
+ return _owner != LOCK_UNOWNED;
+
+ return (_owner & LOCK_ANONYMOUS_OWNED) != LOCK_UNOWNED;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the lock is currently held by any thread.
+ /// </summary>
+ /// <summary>
+ /// Gets whether the lock is held by the current thread.
+ /// </summary>
+ /// <remarks>
+ /// If the lock was initialized to track owner threads, this will return whether the lock is acquired
+ /// by the current thread. It is invalid to use this property when the lock was initialized to not
+ /// track thread ownership.
+ /// </remarks>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// Thread ownership tracking is disabled.
+ /// </exception>
+ public bool IsHeldByCurrentThread
+ {
+ get
+ {
+ if (!IsThreadOwnerTrackingEnabled)
+ {
+ throw new InvalidOperationException(SR.SpinLock_IsHeldByCurrentThread);
+ }
+ return ((_owner & (~LOCK_ID_DISABLE_MASK)) == Environment.CurrentManagedThreadId);
+ }
+ }
+
+ /// <summary>Gets whether thread ownership tracking is enabled for this instance.</summary>
+ public bool IsThreadOwnerTrackingEnabled => (_owner & LOCK_ID_DISABLE_MASK) == 0;
+
+ #region Debugger proxy class
+ /// <summary>
+ /// Internal class used by debug type proxy attribute to display the owner thread ID
+ /// </summary>
+ internal class SystemThreading_SpinLockDebugView
+ {
+ // SpinLock object
+ private SpinLock _spinLock;
+
+ /// <summary>
+ /// SystemThreading_SpinLockDebugView constructor
+ /// </summary>
+ /// <param name="spinLock">The SpinLock to be proxied.</param>
+ public SystemThreading_SpinLockDebugView(SpinLock spinLock)
+ {
+ // Note that this makes a copy of the SpinLock (struct). It doesn't hold a reference to it.
+ _spinLock = spinLock;
+ }
+
+ /// <summary>
+ /// Checks if the lock is held by the current thread or not
+ /// </summary>
+ public bool? IsHeldByCurrentThread
+ {
+ get
+ {
+ try
+ {
+ return _spinLock.IsHeldByCurrentThread;
+ }
+ catch (InvalidOperationException)
+ {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the current owner thread, zero if it is released
+ /// </summary>
+ public int? OwnerThreadID
+ {
+ get
+ {
+ if (_spinLock.IsThreadOwnerTrackingEnabled)
+ {
+ return _spinLock._owner;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Gets whether the lock is currently held by any thread or not.
+ /// </summary>
+ public bool IsHeld => _spinLock.IsHeld;
+ }
+ #endregion
+
+ }
+}
+#pragma warning restore 0420
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs b/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs
index 414ad1852..54857c322 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs
@@ -88,7 +88,16 @@ namespace System.Threading
/// for here.
/// </remarks>
internal static readonly int SpinCountforSpinBeforeWait = PlatformHelper.IsSingleProcessor ? 1 : 35;
- internal const int Sleep1ThresholdForSpinBeforeWait = 40; // should be greater than SpinCountforSpinBeforeWait
+
+ /// <summary>
+ /// Typically, Sleep(1) should not be issued for a spin-wait before a proper wait because it is usually more beneficial
+ /// to just issue the proper wait. For longer spin-waits (when the spin count is configurable), this value may be used as
+ /// a threshold for issuing Sleep(1).
+ /// </summary>
+ /// <remarks>
+ /// Should be greater than <see cref="SpinCountforSpinBeforeWait"/> so that Sleep(1) would not be used by default.
+ /// </remarks>
+ internal const int Sleep1ThresholdForLongSpinBeforeWait = 40;
// The number of times we've spun already.
private int _count;
@@ -127,12 +136,42 @@ namespace System.Threading
/// </remarks>
public void SpinOnce()
{
- SpinOnce(DefaultSleep1Threshold);
+ SpinOnceCore(DefaultSleep1Threshold);
+ }
+
+ /// <summary>
+ /// Performs a single spin.
+ /// </summary>
+ /// <param name="sleep1Threshold">
+ /// A minimum spin count after which <code>Thread.Sleep(1)</code> may be used. A value of <code>-1</code> may be used to
+ /// disable the use of <code>Thread.Sleep(1)</code>.
+ /// </param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sleep1Threshold"/> is less than <code>-1</code>.
+ /// </exception>
+ /// <remarks>
+ /// This is typically called in a loop, and may change in behavior based on the number of times a
+ /// <see cref="SpinOnce"/> has been called thus far on this instance.
+ /// </remarks>
+ public void SpinOnce(int sleep1Threshold)
+ {
+ if (sleep1Threshold < -1)
+ {
+ throw new ArgumentOutOfRangeException(nameof(sleep1Threshold), sleep1Threshold, SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
+ }
+
+ if (sleep1Threshold >= 0 && sleep1Threshold < YieldThreshold)
+ {
+ sleep1Threshold = YieldThreshold;
+ }
+
+ SpinOnceCore(sleep1Threshold);
}
- internal void SpinOnce(int sleep1Threshold)
+ private void SpinOnceCore(int sleep1Threshold)
{
- Debug.Assert(sleep1Threshold >= YieldThreshold || PlatformHelper.IsSingleProcessor); // so that NextSpinWillYield behaves as requested
+ Debug.Assert(sleep1Threshold >= -1);
+ Debug.Assert(sleep1Threshold < 0 || sleep1Threshold >= YieldThreshold);
// (_count - YieldThreshold) % 2 == 0: The purpose of this check is to interleave Thread.Yield/Sleep(0) with
// Thread.SpinWait. Otherwise, the following issues occur:
@@ -145,7 +184,7 @@ namespace System.Threading
// contention), they may switch between one another, delaying work that can make progress.
if ((
_count >= YieldThreshold &&
- (_count >= sleep1Threshold || (_count - YieldThreshold) % 2 == 0)
+ ((_count >= sleep1Threshold && sleep1Threshold >= 0) || (_count - YieldThreshold) % 2 == 0)
) ||
PlatformHelper.IsSingleProcessor)
{
@@ -164,7 +203,7 @@ namespace System.Threading
// configured to use the (default) coarse-grained system timer.
//
- if (_count >= sleep1Threshold)
+ if (_count >= sleep1Threshold && sleep1Threshold >= 0)
{
RuntimeThread.Sleep(1);
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs b/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs
index e050e1539..3b5d31f3c 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs
@@ -26,13 +26,13 @@ namespace System.Threading
HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
- public SynchronizationLockException(String message)
+ public SynchronizationLockException(string message)
: base(message)
{
HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
- public SynchronizationLockException(String message, Exception innerException)
+ public SynchronizationLockException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
new file mode 100644
index 000000000..baf0a5025
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
@@ -0,0 +1,754 @@
+// 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.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A pair of schedulers that together support concurrent (reader) / exclusive (writer)
+// task scheduling. Using just the exclusive scheduler can be used to simulate a serial
+// processing queue, and using just the concurrent scheduler with a specified
+// MaximumConcurrentlyLevel can be used to achieve a MaxDegreeOfParallelism across
+// a bunch of tasks, parallel loops, dataflow blocks, etc.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+
+using Thread = Internal.Runtime.Augments.RuntimeThread;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Provides concurrent and exclusive task schedulers that coordinate to execute
+ /// tasks while ensuring that concurrent tasks may run concurrently and exclusive tasks never do.
+ /// </summary>
+ [DebuggerDisplay("Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger}")]
+ [DebuggerTypeProxy(typeof(ConcurrentExclusiveSchedulerPair.DebugView))]
+ public class ConcurrentExclusiveSchedulerPair
+ {
+ /// <summary>A processing mode to denote what kinds of tasks are currently being processed on this thread.</summary>
+ private readonly ThreadLocal<ProcessingMode> m_threadProcessingMode = new ThreadLocal<ProcessingMode>();
+ /// <summary>The scheduler used to queue and execute "concurrent" tasks that may run concurrently with other concurrent tasks.</summary>
+ private readonly ConcurrentExclusiveTaskScheduler m_concurrentTaskScheduler;
+ /// <summary>The scheduler used to queue and execute "exclusive" tasks that must run exclusively while no other tasks for this pair are running.</summary>
+ private readonly ConcurrentExclusiveTaskScheduler m_exclusiveTaskScheduler;
+ /// <summary>The underlying task scheduler to which all work should be scheduled.</summary>
+ private readonly TaskScheduler m_underlyingTaskScheduler;
+ /// <summary>
+ /// The maximum number of tasks allowed to run concurrently. This only applies to concurrent tasks,
+ /// since exclusive tasks are inherently limited to 1.
+ /// </summary>
+ private readonly int m_maxConcurrencyLevel;
+ /// <summary>The maximum number of tasks we can process before recycling our runner tasks.</summary>
+ private readonly int m_maxItemsPerTask;
+ /// <summary>
+ /// If positive, it represents the number of concurrently running concurrent tasks.
+ /// If negative, it means an exclusive task has been scheduled.
+ /// If 0, nothing has been scheduled.
+ /// </summary>
+ private int m_processingCount;
+ /// <summary>Completion state for a task representing the completion of this pair.</summary>
+ /// <remarks>Lazily-initialized only if the scheduler pair is shutting down or if the Completion is requested.</remarks>
+ private CompletionState m_completionState;
+
+ /// <summary>A constant value used to signal unlimited processing.</summary>
+ private const int UNLIMITED_PROCESSING = -1;
+ /// <summary>Constant used for m_processingCount to indicate that an exclusive task is being processed.</summary>
+ private const int EXCLUSIVE_PROCESSING_SENTINEL = -1;
+ /// <summary>Default MaxItemsPerTask to use for processing if none is specified.</summary>
+ private const int DEFAULT_MAXITEMSPERTASK = UNLIMITED_PROCESSING;
+ /// <summary>Default MaxConcurrencyLevel is the processor count if not otherwise specified.</summary>
+ private static int DefaultMaxConcurrencyLevel { get { return Environment.ProcessorCount; } }
+
+ /// <summary>Gets the sync obj used to protect all state on this instance.</summary>
+ private object ValueLock { get { return m_threadProcessingMode; } }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair.
+ /// </summary>
+ public ConcurrentExclusiveSchedulerPair() :
+ this(TaskScheduler.Default, DefaultMaxConcurrencyLevel, DEFAULT_MAXITEMSPERTASK)
+ { }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler.
+ /// </summary>
+ /// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
+ public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler) :
+ this(taskScheduler, DefaultMaxConcurrencyLevel, DEFAULT_MAXITEMSPERTASK)
+ { }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler with a maximum concurrency level.
+ /// </summary>
+ /// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
+ /// <param name="maxConcurrencyLevel">The maximum number of tasks to run concurrently.</param>
+ public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler, int maxConcurrencyLevel) :
+ this(taskScheduler, maxConcurrencyLevel, DEFAULT_MAXITEMSPERTASK)
+ { }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler with a maximum
+ /// concurrency level and a maximum number of scheduled tasks that may be processed as a unit.
+ /// </summary>
+ /// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
+ /// <param name="maxConcurrencyLevel">The maximum number of tasks to run concurrently.</param>
+ /// <param name="maxItemsPerTask">The maximum number of tasks to process for each underlying scheduled task used by the pair.</param>
+ public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask)
+ {
+ // Validate arguments
+ if (taskScheduler == null) throw new ArgumentNullException(nameof(taskScheduler));
+ if (maxConcurrencyLevel == 0 || maxConcurrencyLevel < -1) throw new ArgumentOutOfRangeException(nameof(maxConcurrencyLevel));
+ if (maxItemsPerTask == 0 || maxItemsPerTask < -1) throw new ArgumentOutOfRangeException(nameof(maxItemsPerTask));
+
+ // Store configuration
+ m_underlyingTaskScheduler = taskScheduler;
+ m_maxConcurrencyLevel = maxConcurrencyLevel;
+ m_maxItemsPerTask = maxItemsPerTask;
+
+ // Downgrade to the underlying scheduler's max degree of parallelism if it's lower than the user-supplied level
+ int mcl = taskScheduler.MaximumConcurrencyLevel;
+ if (mcl > 0 && mcl < m_maxConcurrencyLevel) m_maxConcurrencyLevel = mcl;
+
+ // Treat UNLIMITED_PROCESSING/-1 for both MCL and MIPT as the biggest possible value so that we don't
+ // have to special case UNLIMITED_PROCESSING later on in processing.
+ if (m_maxConcurrencyLevel == UNLIMITED_PROCESSING) m_maxConcurrencyLevel = int.MaxValue;
+ if (m_maxItemsPerTask == UNLIMITED_PROCESSING) m_maxItemsPerTask = int.MaxValue;
+
+ // Create the concurrent/exclusive schedulers for this pair
+ m_exclusiveTaskScheduler = new ConcurrentExclusiveTaskScheduler(this, 1, ProcessingMode.ProcessingExclusiveTask);
+ m_concurrentTaskScheduler = new ConcurrentExclusiveTaskScheduler(this, m_maxConcurrencyLevel, ProcessingMode.ProcessingConcurrentTasks);
+ }
+
+ /// <summary>Informs the scheduler pair that it should not accept any more tasks.</summary>
+ /// <remarks>
+ /// Calling <see cref="Complete"/> is optional, and it's only necessary if the <see cref="Completion"/>
+ /// will be relied on for notification of all processing being completed.
+ /// </remarks>
+ public void Complete()
+ {
+ lock (ValueLock)
+ {
+ if (!CompletionRequested)
+ {
+ RequestCompletion();
+ CleanupStateIfCompletingAndQuiesced();
+ }
+ }
+ }
+
+ /// <summary>Gets a <see cref="System.Threading.Tasks.Task"/> that will complete when the scheduler has completed processing.</summary>
+ public Task Completion
+ {
+ // ValueLock not needed, but it's ok if it's held
+ get { return EnsureCompletionStateInitialized().Task; }
+ }
+
+ /// <summary>Gets the lazily-initialized completion state.</summary>
+ private CompletionState EnsureCompletionStateInitialized()
+ {
+ // ValueLock not needed, but it's ok if it's held
+ return LazyInitializer.EnsureInitialized(ref m_completionState, () => new CompletionState());
+ }
+
+ /// <summary>Gets whether completion has been requested.</summary>
+ private bool CompletionRequested
+ {
+ // ValueLock not needed, but it's ok if it's held
+ get { return m_completionState != null && Volatile.Read(ref m_completionState.m_completionRequested); }
+ }
+
+ /// <summary>Sets that completion has been requested.</summary>
+ private void RequestCompletion()
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+ EnsureCompletionStateInitialized().m_completionRequested = true;
+ }
+
+ /// <summary>
+ /// Cleans up state if and only if there's no processing currently happening
+ /// and no more to be done later.
+ /// </summary>
+ private void CleanupStateIfCompletingAndQuiesced()
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+ if (ReadyToComplete) CompleteTaskAsync();
+ }
+
+ /// <summary>Gets whether the pair is ready to complete.</summary>
+ private bool ReadyToComplete
+ {
+ get
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // We can only complete if completion has been requested and no processing is currently happening.
+ if (!CompletionRequested || m_processingCount != 0) return false;
+
+ // Now, only allow shutdown if an exception occurred or if there are no more tasks to process.
+ var cs = EnsureCompletionStateInitialized();
+ return
+ (cs.m_exceptions != null && cs.m_exceptions.Count > 0) ||
+ (m_concurrentTaskScheduler.m_tasks.IsEmpty && m_exclusiveTaskScheduler.m_tasks.IsEmpty);
+ }
+ }
+
+ /// <summary>Completes the completion task asynchronously.</summary>
+ private void CompleteTaskAsync()
+ {
+ Debug.Assert(ReadyToComplete, "The block must be ready to complete to be here.");
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // Ensure we only try to complete once, then schedule completion
+ // in order to escape held locks and the caller's context
+ var cs = EnsureCompletionStateInitialized();
+ if (!cs.m_completionQueued)
+ {
+ cs.m_completionQueued = true;
+ ThreadPool.QueueUserWorkItem(state =>
+ {
+ var localThis = (ConcurrentExclusiveSchedulerPair)state;
+ Debug.Assert(!localThis.m_completionState.Task.IsCompleted, "Completion should only happen once.");
+
+ List<Exception> exceptions = localThis.m_completionState.m_exceptions;
+ bool success = (exceptions != null && exceptions.Count > 0) ?
+ localThis.m_completionState.TrySetException(exceptions) :
+ localThis.m_completionState.TrySetResult(default);
+ Debug.Assert(success, "Expected to complete completion task.");
+
+ localThis.m_threadProcessingMode.Dispose();
+ }, this);
+ }
+ }
+
+ /// <summary>Initiates scheduler shutdown due to a worker task faulting.</summary>
+ /// <param name="faultedTask">The faulted worker task that's initiating the shutdown.</param>
+ private void FaultWithTask(Task faultedTask)
+ {
+ Debug.Assert(faultedTask != null && faultedTask.IsFaulted && faultedTask.Exception.InnerExceptions.Count > 0,
+ "Needs a task in the faulted state and thus with exceptions.");
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // Store the faulted task's exceptions
+ var cs = EnsureCompletionStateInitialized();
+ if (cs.m_exceptions == null) cs.m_exceptions = new List<Exception>();
+ cs.m_exceptions.AddRange(faultedTask.Exception.InnerExceptions);
+
+ // Now that we're doomed, request completion
+ RequestCompletion();
+ }
+
+ /// <summary>
+ /// Gets a TaskScheduler that can be used to schedule tasks to this pair
+ /// that may run concurrently with other tasks on this pair.
+ /// </summary>
+ public TaskScheduler ConcurrentScheduler { get { return m_concurrentTaskScheduler; } }
+ /// <summary>
+ /// Gets a TaskScheduler that can be used to schedule tasks to this pair
+ /// that must run exclusively with regards to other tasks on this pair.
+ /// </summary>
+ public TaskScheduler ExclusiveScheduler { get { return m_exclusiveTaskScheduler; } }
+
+ /// <summary>Gets the number of tasks waiting to run concurrently.</summary>
+ /// <remarks>This does not take the necessary lock, as it's only called from under the debugger.</remarks>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private int ConcurrentTaskCountForDebugger { get { return m_concurrentTaskScheduler.m_tasks.Count; } }
+
+ /// <summary>Gets the number of tasks waiting to run exclusively.</summary>
+ /// <remarks>This does not take the necessary lock, as it's only called from under the debugger.</remarks>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private int ExclusiveTaskCountForDebugger { get { return m_exclusiveTaskScheduler.m_tasks.Count; } }
+
+ /// <summary>Notifies the pair that new work has arrived to be processed.</summary>
+ /// <param name="fairly">Whether tasks should be scheduled fairly with regards to other tasks.</param>
+ /// <remarks>Must only be called while holding the lock.</remarks>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")]
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
+ private void ProcessAsyncIfNecessary(bool fairly = false)
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // If the current processing count is >= 0, we can potentially launch further processing.
+ if (m_processingCount >= 0)
+ {
+ // We snap whether there are any exclusive tasks or concurrent tasks waiting.
+ // (We grab the concurrent count below only once we know we need it.)
+ // With processing happening concurrent to this operation, this data may
+ // immediately be out of date, but it can only go from non-empty
+ // to empty and not the other way around. As such, this is safe,
+ // as worst case is we'll schedule an extra task when we didn't
+ // otherwise need to, and we'll just eat its overhead.
+ bool exclusiveTasksAreWaiting = !m_exclusiveTaskScheduler.m_tasks.IsEmpty;
+
+ // If there's no processing currently happening but there are waiting exclusive tasks,
+ // let's start processing those exclusive tasks.
+ Task processingTask = null;
+ if (m_processingCount == 0 && exclusiveTasksAreWaiting)
+ {
+ // Launch exclusive task processing
+ m_processingCount = EXCLUSIVE_PROCESSING_SENTINEL; // -1
+ try
+ {
+ processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessExclusiveTasks(), this,
+ default, GetCreationOptionsForTask(fairly));
+ processingTask.Start(m_underlyingTaskScheduler);
+ // When we call Start, if the underlying scheduler throws in QueueTask, TPL will fault the task and rethrow
+ // the exception. To deal with that, we need a reference to the task object, so that we can observe its exception.
+ // Hence, we separate creation and starting, so that we can store a reference to the task before we attempt QueueTask.
+ }
+ catch
+ {
+ m_processingCount = 0;
+ FaultWithTask(processingTask);
+ }
+ }
+ // If there are no waiting exclusive tasks, there are concurrent tasks, and we haven't reached our maximum
+ // concurrency level for processing, let's start processing more concurrent tasks.
+ else
+ {
+ int concurrentTasksWaitingCount = m_concurrentTaskScheduler.m_tasks.Count;
+
+ if (concurrentTasksWaitingCount > 0 && !exclusiveTasksAreWaiting && m_processingCount < m_maxConcurrencyLevel)
+ {
+ // Launch concurrent task processing, up to the allowed limit
+ for (int i = 0; i < concurrentTasksWaitingCount && m_processingCount < m_maxConcurrencyLevel; ++i)
+ {
+ ++m_processingCount;
+ try
+ {
+ processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessConcurrentTasks(), this,
+ default, GetCreationOptionsForTask(fairly));
+ processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew
+ }
+ catch
+ {
+ --m_processingCount;
+ FaultWithTask(processingTask);
+ }
+ }
+ }
+ }
+
+ // Check to see if all tasks have completed and if completion has been requested.
+ CleanupStateIfCompletingAndQuiesced();
+ }
+ else Debug.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing count must be the sentinel if it's not >= 0.");
+ }
+
+ /// <summary>
+ /// Processes exclusive tasks serially until either there are no more to process
+ /// or we've reached our user-specified maximum limit.
+ /// </summary>
+ private void ProcessExclusiveTasks()
+ {
+ Debug.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "Processing exclusive tasks requires being in exclusive mode.");
+ Debug.Assert(!m_exclusiveTaskScheduler.m_tasks.IsEmpty, "Processing exclusive tasks requires tasks to be processed.");
+ ContractAssertMonitorStatus(ValueLock, held: false);
+ try
+ {
+ // Note that we're processing exclusive tasks on the current thread
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.NotCurrentlyProcessing,
+ "This thread should not yet be involved in this pair's processing.");
+ m_threadProcessingMode.Value = ProcessingMode.ProcessingExclusiveTask;
+
+ // Process up to the maximum number of items per task allowed
+ for (int i = 0; i < m_maxItemsPerTask; i++)
+ {
+ // Get the next available exclusive task. If we can't find one, bail.
+ Task exclusiveTask;
+ if (!m_exclusiveTaskScheduler.m_tasks.TryDequeue(out exclusiveTask)) break;
+
+ // Execute the task. If the scheduler was previously faulted,
+ // this task could have been faulted when it was queued; ignore such tasks.
+ if (!exclusiveTask.IsFaulted) m_exclusiveTaskScheduler.ExecuteTask(exclusiveTask);
+ }
+ }
+ finally
+ {
+ // We're no longer processing exclusive tasks on the current thread
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.ProcessingExclusiveTask,
+ "Somehow we ended up escaping exclusive mode.");
+ m_threadProcessingMode.Value = ProcessingMode.NotCurrentlyProcessing;
+
+ lock (ValueLock)
+ {
+ // When this task was launched, we tracked it by setting m_processingCount to WRITER_IN_PROGRESS.
+ // now reset it to 0. Then check to see whether there's more processing to be done.
+ // There might be more concurrent tasks available, for example, if concurrent tasks arrived
+ // after we exited the loop, or if we exited the loop while concurrent tasks were still
+ // available but we hit our maxItemsPerTask limit.
+ Debug.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing mode should not have deviated from exclusive.");
+ m_processingCount = 0;
+ ProcessAsyncIfNecessary(true);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Processes concurrent tasks serially until either there are no more to process,
+ /// we've reached our user-specified maximum limit, or exclusive tasks have arrived.
+ /// </summary>
+ private void ProcessConcurrentTasks()
+ {
+ Debug.Assert(m_processingCount > 0, "Processing concurrent tasks requires us to be in concurrent mode.");
+ ContractAssertMonitorStatus(ValueLock, held: false);
+ try
+ {
+ // Note that we're processing concurrent tasks on the current thread
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.NotCurrentlyProcessing,
+ "This thread should not yet be involved in this pair's processing.");
+ m_threadProcessingMode.Value = ProcessingMode.ProcessingConcurrentTasks;
+
+ // Process up to the maximum number of items per task allowed
+ for (int i = 0; i < m_maxItemsPerTask; i++)
+ {
+ // Get the next available concurrent task. If we can't find one, bail.
+ Task concurrentTask;
+ if (!m_concurrentTaskScheduler.m_tasks.TryDequeue(out concurrentTask)) break;
+
+ // Execute the task. If the scheduler was previously faulted,
+ // this task could have been faulted when it was queued; ignore such tasks.
+ if (!concurrentTask.IsFaulted) m_concurrentTaskScheduler.ExecuteTask(concurrentTask);
+
+ // Now check to see if exclusive tasks have arrived; if any have, they take priority
+ // so we'll bail out here. Note that we could have checked this condition
+ // in the for loop's condition, but that could lead to extra overhead
+ // in the case where a concurrent task arrives, this task is launched, and then
+ // before entering the loop an exclusive task arrives. If we didn't execute at
+ // least one task, we would have spent all of the overhead to launch a
+ // task but with none of the benefit. There's of course also an inherent
+ // race condition here with regards to exclusive tasks arriving, and we're ok with
+ // executing one more concurrent task than we should before giving priority to exclusive tasks.
+ if (!m_exclusiveTaskScheduler.m_tasks.IsEmpty) break;
+ }
+ }
+ finally
+ {
+ // We're no longer processing concurrent tasks on the current thread
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.ProcessingConcurrentTasks,
+ "Somehow we ended up escaping concurrent mode.");
+ m_threadProcessingMode.Value = ProcessingMode.NotCurrentlyProcessing;
+
+ lock (ValueLock)
+ {
+ // When this task was launched, we tracked it with a positive processing count;
+ // decrement that count. Then check to see whether there's more processing to be done.
+ // There might be more concurrent tasks available, for example, if concurrent tasks arrived
+ // after we exited the loop, or if we exited the loop while concurrent tasks were still
+ // available but we hit our maxItemsPerTask limit.
+ Debug.Assert(m_processingCount > 0, "The procesing mode should not have deviated from concurrent.");
+ if (m_processingCount > 0) --m_processingCount;
+ ProcessAsyncIfNecessary(true);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Holder for lazily-initialized state about the completion of a scheduler pair.
+ /// Completion is only triggered either by rare exceptional conditions or by
+ /// the user calling Complete, and as such we only lazily initialize this
+ /// state in one of those conditions or if the user explicitly asks for
+ /// the Completion.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
+ private sealed class CompletionState : TaskCompletionSource<VoidTaskResult>
+ {
+ /// <summary>Whether the scheduler has had completion requested.</summary>
+ /// <remarks>This variable is not volatile, so to gurantee safe reading reads, Volatile.Read is used in TryExecuteTaskInline.</remarks>
+ internal bool m_completionRequested;
+ /// <summary>Whether completion processing has been queued.</summary>
+ internal bool m_completionQueued;
+ /// <summary>Unrecoverable exceptions incurred while processing.</summary>
+ internal List<Exception> m_exceptions;
+ }
+
+ /// <summary>
+ /// A scheduler shim used to queue tasks to the pair and execute those tasks on request of the pair.
+ /// </summary>
+ [DebuggerDisplay("Count={CountForDebugger}, MaxConcurrencyLevel={m_maxConcurrencyLevel}, Id={Id}")]
+ [DebuggerTypeProxy(typeof(ConcurrentExclusiveTaskScheduler.DebugView))]
+ private sealed class ConcurrentExclusiveTaskScheduler : TaskScheduler
+ {
+ /// <summary>Cached delegate for invoking TryExecuteTaskShim.</summary>
+ private static readonly Func<object, bool> s_tryExecuteTaskShim = new Func<object, bool>(TryExecuteTaskShim);
+ /// <summary>The parent pair.</summary>
+ private readonly ConcurrentExclusiveSchedulerPair m_pair;
+ /// <summary>The maximum concurrency level for the scheduler.</summary>
+ private readonly int m_maxConcurrencyLevel;
+ /// <summary>The processing mode of this scheduler, exclusive or concurrent.</summary>
+ private readonly ProcessingMode m_processingMode;
+ /// <summary>Gets the queue of tasks for this scheduler.</summary>
+ internal readonly IProducerConsumerQueue<Task> m_tasks;
+
+ /// <summary>Initializes the scheduler.</summary>
+ /// <param name="pair">The parent pair.</param>
+ /// <param name="maxConcurrencyLevel">The maximum degree of concurrency this scheduler may use.</param>
+ /// <param name="processingMode">The processing mode of this scheduler.</param>
+ internal ConcurrentExclusiveTaskScheduler(ConcurrentExclusiveSchedulerPair pair, int maxConcurrencyLevel, ProcessingMode processingMode)
+ {
+ Debug.Assert(pair != null, "Scheduler must be associated with a valid pair.");
+ Debug.Assert(processingMode == ProcessingMode.ProcessingConcurrentTasks || processingMode == ProcessingMode.ProcessingExclusiveTask,
+ "Scheduler must be for concurrent or exclusive processing.");
+ Debug.Assert(
+ (processingMode == ProcessingMode.ProcessingConcurrentTasks && (maxConcurrencyLevel >= 1 || maxConcurrencyLevel == UNLIMITED_PROCESSING)) ||
+ (processingMode == ProcessingMode.ProcessingExclusiveTask && maxConcurrencyLevel == 1),
+ "If we're in concurrent mode, our concurrency level should be positive or unlimited. If exclusive, it should be 1.");
+
+ m_pair = pair;
+ m_maxConcurrencyLevel = maxConcurrencyLevel;
+ m_processingMode = processingMode;
+ m_tasks = (processingMode == ProcessingMode.ProcessingExclusiveTask) ?
+ (IProducerConsumerQueue<Task>)new SingleProducerSingleConsumerQueue<Task>() :
+ (IProducerConsumerQueue<Task>)new MultiProducerMultiConsumerQueue<Task>();
+ }
+
+ /// <summary>Gets the maximum concurrency level this scheduler is able to support.</summary>
+ public override int MaximumConcurrencyLevel { get { return m_maxConcurrencyLevel; } }
+
+ /// <summary>Queues a task to the scheduler.</summary>
+ /// <param name="task">The task to be queued.</param>
+ protected internal override void QueueTask(Task task)
+ {
+ Debug.Assert(task != null, "Infrastructure should have provided a non-null task.");
+ lock (m_pair.ValueLock)
+ {
+ // If the scheduler has already had completion requested, no new work is allowed to be scheduled
+ if (m_pair.CompletionRequested) throw new InvalidOperationException(GetType().ToString());
+
+ // Queue the task, and then let the pair know that more work is now available to be scheduled
+ m_tasks.Enqueue(task);
+ m_pair.ProcessAsyncIfNecessary();
+ }
+ }
+
+ /// <summary>Executes a task on this scheduler.</summary>
+ /// <param name="task">The task to be executed.</param>
+ internal void ExecuteTask(Task task)
+ {
+ Debug.Assert(task != null, "Infrastructure should have provided a non-null task.");
+ base.TryExecuteTask(task);
+ }
+
+ /// <summary>Tries to execute the task synchronously on this scheduler.</summary>
+ /// <param name="task">The task to execute.</param>
+ /// <param name="taskWasPreviouslyQueued">Whether the task was previously queued to the scheduler.</param>
+ /// <returns>true if the task could be executed; otherwise, false.</returns>
+ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ Debug.Assert(task != null, "Infrastructure should have provided a non-null task.");
+
+ // If the scheduler has had completion requested, no new work is allowed to be scheduled.
+ // A non-locked read on m_completionRequested (in CompletionRequested) is acceptable here because:
+ // a) we don't need to be exact... a Complete call could come in later in the function anyway
+ // b) this is only a fast path escape hatch. To actually inline the task,
+ // we need to be inside of an already executing task, and in such a case,
+ // while completion may have been requested, we can't have shutdown yet.
+ if (!taskWasPreviouslyQueued && m_pair.CompletionRequested) return false;
+
+ // We know the implementation of the default scheduler and how it will behave.
+ // As it's the most common underlying scheduler, we optimize for it.
+ bool isDefaultScheduler = m_pair.m_underlyingTaskScheduler == TaskScheduler.Default;
+
+ // If we're targeting the default scheduler and taskWasPreviouslyQueued is true,
+ // we know that the default scheduler will only allow it to be inlined
+ // if we're on a thread pool thread (but it won't always allow it in that case,
+ // since it'll only allow inlining if it can find the task in the local queue).
+ // As such, if we're not on a thread pool thread, we know for sure the
+ // task won't be inlined, so let's not even try.
+ if (isDefaultScheduler && taskWasPreviouslyQueued && !Thread.CurrentThread.IsThreadPoolThread)
+ {
+ return false;
+ }
+ else
+ {
+ // If a task is already running on this thread, allow inline execution to proceed.
+ // If there's already a task from this scheduler running on the current thread, we know it's safe
+ // to run this task, in effect temporarily taking that task's count allocation.
+ if (m_pair.m_threadProcessingMode.Value == m_processingMode)
+ {
+ // If we're targeting the default scheduler and taskWasPreviouslyQueued is false,
+ // we know the default scheduler will allow it, so we can just execute it here.
+ // Otherwise, delegate to the target scheduler's inlining.
+ return (isDefaultScheduler && !taskWasPreviouslyQueued) ?
+ TryExecuteTask(task) :
+ TryExecuteTaskInlineOnTargetScheduler(task);
+ }
+ }
+
+ // We're not in the context of a task already executing on this scheduler. Bail.
+ return false;
+ }
+
+ /// <summary>
+ /// Implements a reasonable approximation for TryExecuteTaskInline on the underlying scheduler,
+ /// which we can't call directly on the underlying scheduler.
+ /// </summary>
+ /// <param name="task">The task to execute inline if possible.</param>
+ /// <returns>true if the task was inlined successfully; otherwise, false.</returns>
+ [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "ignored")]
+ private bool TryExecuteTaskInlineOnTargetScheduler(Task task)
+ {
+ // We'd like to simply call TryExecuteTaskInline here, but we can't.
+ // As there's no built-in API for this, a workaround is to create a new task that,
+ // when executed, will simply call TryExecuteTask to run the real task, and then
+ // we run our new shim task synchronously on the target scheduler. If all goes well,
+ // our synchronous invocation will succeed in running the shim task on the current thread,
+ // which will in turn run the real task on the current thread. If the scheduler
+ // doesn't allow that execution, RunSynchronously will block until the underlying scheduler
+ // is able to invoke the task, which might account for an additional but unavoidable delay.
+ // Once it's done, we can return whether the task executed by returning the
+ // shim task's Result, which is in turn the result of TryExecuteTask.
+ var t = new Task<bool>(s_tryExecuteTaskShim, Tuple.Create(this, task));
+ try
+ {
+ t.RunSynchronously(m_pair.m_underlyingTaskScheduler);
+ return t.Result;
+ }
+ catch
+ {
+ Debug.Assert(t.IsFaulted, "Task should be faulted due to the scheduler faulting it and throwing the exception.");
+ var ignored = t.Exception;
+ throw;
+ }
+ finally { t.Dispose(); }
+ }
+
+ /// <summary>Shim used to invoke this.TryExecuteTask(task).</summary>
+ /// <param name="state">A tuple of the ConcurrentExclusiveTaskScheduler and the task to execute.</param>
+ /// <returns>true if the task was successfully inlined; otherwise, false.</returns>
+ /// <remarks>
+ /// This method is separated out not because of performance reasons but so that
+ /// the SecuritySafeCritical attribute may be employed.
+ /// </remarks>
+ private static bool TryExecuteTaskShim(object state)
+ {
+ var tuple = (Tuple<ConcurrentExclusiveTaskScheduler, Task>)state;
+ return tuple.Item1.TryExecuteTask(tuple.Item2);
+ }
+
+ /// <summary>Gets for debugging purposes the tasks scheduled to this scheduler.</summary>
+ /// <returns>An enumerable of the tasks queued.</returns>
+ protected override IEnumerable<Task> GetScheduledTasks() { return m_tasks; }
+
+ /// <summary>Gets the number of tasks queued to this scheduler.</summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private int CountForDebugger { get { return m_tasks.Count; } }
+
+ /// <summary>Provides a debug view for ConcurrentExclusiveTaskScheduler.</summary>
+ private sealed class DebugView
+ {
+ /// <summary>The scheduler being debugged.</summary>
+ private readonly ConcurrentExclusiveTaskScheduler m_taskScheduler;
+
+ /// <summary>Initializes the debug view.</summary>
+ /// <param name="scheduler">The scheduler being debugged.</param>
+ public DebugView(ConcurrentExclusiveTaskScheduler scheduler)
+ {
+ Debug.Assert(scheduler != null, "Need a scheduler with which to construct the debug view.");
+ m_taskScheduler = scheduler;
+ }
+
+ /// <summary>Gets this pair's maximum allowed concurrency level.</summary>
+ public int MaximumConcurrencyLevel { get { return m_taskScheduler.m_maxConcurrencyLevel; } }
+ /// <summary>Gets the tasks scheduled to this scheduler.</summary>
+ public IEnumerable<Task> ScheduledTasks { get { return m_taskScheduler.m_tasks; } }
+ /// <summary>Gets the scheduler pair with which this scheduler is associated.</summary>
+ public ConcurrentExclusiveSchedulerPair SchedulerPair { get { return m_taskScheduler.m_pair; } }
+ }
+ }
+
+ /// <summary>Provides a debug view for ConcurrentExclusiveSchedulerPair.</summary>
+ private sealed class DebugView
+ {
+ /// <summary>The pair being debugged.</summary>
+ private readonly ConcurrentExclusiveSchedulerPair m_pair;
+
+ /// <summary>Initializes the debug view.</summary>
+ /// <param name="pair">The pair being debugged.</param>
+ public DebugView(ConcurrentExclusiveSchedulerPair pair)
+ {
+ Debug.Assert(pair != null, "Need a pair with which to construct the debug view.");
+ m_pair = pair;
+ }
+
+ /// <summary>Gets a representation of the execution state of the pair.</summary>
+ public ProcessingMode Mode { get { return m_pair.ModeForDebugger; } }
+ /// <summary>Gets the number of tasks waiting to run exclusively.</summary>
+ public IEnumerable<Task> ScheduledExclusive { get { return m_pair.m_exclusiveTaskScheduler.m_tasks; } }
+ /// <summary>Gets the number of tasks waiting to run concurrently.</summary>
+ public IEnumerable<Task> ScheduledConcurrent { get { return m_pair.m_concurrentTaskScheduler.m_tasks; } }
+ /// <summary>Gets the number of tasks currently being executed.</summary>
+ public int CurrentlyExecutingTaskCount
+ {
+ get { return (m_pair.m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL) ? 1 : m_pair.m_processingCount; }
+ }
+ /// <summary>Gets the underlying task scheduler that actually executes the tasks.</summary>
+ public TaskScheduler TargetScheduler { get { return m_pair.m_underlyingTaskScheduler; } }
+ }
+
+ /// <summary>Gets an enumeration for debugging that represents the current state of the scheduler pair.</summary>
+ /// <remarks>This is only for debugging. It does not take the necessary locks to be useful for runtime usage.</remarks>
+ private ProcessingMode ModeForDebugger
+ {
+ get
+ {
+ // If our completion task is done, so are we.
+ if (m_completionState != null && m_completionState.Task.IsCompleted) return ProcessingMode.Completed;
+
+ // Otherwise, summarize our current state.
+ var mode = ProcessingMode.NotCurrentlyProcessing;
+ if (m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL) mode |= ProcessingMode.ProcessingExclusiveTask;
+ if (m_processingCount >= 1) mode |= ProcessingMode.ProcessingConcurrentTasks;
+ if (CompletionRequested) mode |= ProcessingMode.Completing;
+ return mode;
+ }
+ }
+
+ /// <summary>Asserts that a given synchronization object is either held or not held.</summary>
+ /// <param name="syncObj">The monitor to check.</param>
+ /// <param name="held">Whether we want to assert that it's currently held or not held.</param>
+ [Conditional("DEBUG")]
+ private static void ContractAssertMonitorStatus(object syncObj, bool held)
+ {
+ Debug.Assert(syncObj != null, "The monitor object to check must be provided.");
+#if !MONO
+ Debug.Assert(Monitor.IsEntered(syncObj) == held, "The locking scheme was not correctly followed.");
+#endif
+ }
+
+ /// <summary>Gets the options to use for tasks.</summary>
+ /// <param name="isReplacementReplica">If this task is being created to replace another.</param>
+ /// <remarks>
+ /// These options should be used for all tasks that have the potential to run user code or
+ /// that are repeatedly spawned and thus need a modicum of fair treatment.
+ /// </remarks>
+ /// <returns>The options to use.</returns>
+ internal static TaskCreationOptions GetCreationOptionsForTask(bool isReplacementReplica = false)
+ {
+ TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
+ if (isReplacementReplica) options |= TaskCreationOptions.PreferFairness;
+ return options;
+ }
+
+ /// <summary>Provides an enumeration that represents the current state of the scheduler pair.</summary>
+ [Flags]
+ private enum ProcessingMode : byte
+ {
+ /// <summary>The scheduler pair is currently dormant, with no work scheduled.</summary>
+ NotCurrentlyProcessing = 0x0,
+ /// <summary>The scheduler pair has queued processing for exclusive tasks.</summary>
+ ProcessingExclusiveTask = 0x1,
+ /// <summary>The scheduler pair has queued processing for concurrent tasks.</summary>
+ ProcessingConcurrentTasks = 0x2,
+ /// <summary>Completion has been requested.</summary>
+ Completing = 0x4,
+ /// <summary>The scheduler pair is finished processing.</summary>
+ Completed = 0x8
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
index a6ec03045..c3ee31a53 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
@@ -54,6 +54,18 @@ namespace System.Threading.Tasks
}
/// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/>
+ /// class with a specified error message, a reference to the inner exception that is the cause of
+ /// this exception, and the <see cref="CancellationToken"/> that triggered the cancellation.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ /// <param name="token">The <see cref="CancellationToken"/> that triggered the cancellation.</param>
+ public TaskCanceledException(string message, Exception innerException, CancellationToken token) : base(message, innerException, token)
+ {
+ }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/> class
/// with a reference to the <see cref="T:System.Threading.Tasks.Task"/> that has been canceled.
/// </summary>
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
index 992e9db76..11ba26d89 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
@@ -315,7 +315,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
public bool TrySetCanceled()
{
- return TrySetCanceled(default(CancellationToken));
+ return TrySetCanceled(default);
}
// Enables a token to be stored into the canceled task
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
index 18e4a27a4..4d6a75960 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
@@ -14,17 +14,59 @@ using Internal.Runtime.CompilerServices;
namespace System.Threading.Tasks
{
+ // TYPE SAFETY WARNING:
+ // This code uses Unsafe.As to cast _obj. This is done in order to minimize the costs associated with
+ // casting _obj to a variety of different types that can be stored in a ValueTask, e.g. Task<TResult>
+ // vs IValueTaskSource<TResult>. Previous attempts at this were faulty due to using a separate field
+ // to store information about the type of the object in _obj; this is faulty because if the ValueTask
+ // is stored into a field, concurrent read/writes can result in tearing the _obj from the type information
+ // stored in a separate field. This means we can rely only on the _obj field to determine how to handle
+ // it. As such, the pattern employed is to copy _obj into a local obj, and then check it for null and
+ // type test against Task/Task<TResult>. Since the ValueTask can only be constructed with null, Task,
+ // or IValueTaskSource, we can then be confident in knowing that if it doesn't match one of those values,
+ // it must be an IValueTaskSource, and we can use Unsafe.As. This could be defeated by other unsafe means,
+ // like private reflection or using Unsafe.As manually, but at that point you're already doing things
+ // that can violate type safety; we only care about getting correct behaviors when using "safe" code.
+ // There are still other race conditions in user's code that can result in errors, but such errors don't
+ // cause ValueTask to violate type safety.
+
/// <summary>Provides an awaitable result of an asynchronous operation.</summary>
/// <remarks>
- /// <see cref="ValueTask"/>s are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task"/>
- /// should be extracted using <see cref="AsTask"/>. Such operations might include caching an instance to be awaited later,
- /// registering multiple continuations with a single operation, awaiting the same task multiple times, and using combinators over
- /// multiple operations.
+ /// <see cref="ValueTask"/> instances are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task"/>
+ /// should be extracted using <see cref="AsTask"/>. Such operations might include caching a task instance to be awaited later,
+ /// registering multiple continuations with a single task, awaiting the same task multiple times, and using combinators over
+ /// multiple operations:
+ /// <list type="bullet">
+ /// <item>
+ /// Once the result of a <see cref="ValueTask"/> instance has been retrieved, do not attempt to retrieve it again.
+ /// <see cref="ValueTask"/> instances may be backed by <see cref="IValueTaskSource"/> instances that are reusable, and such
+ /// instances may use the act of retrieving the instances result as a notification that the instance may now be reused for
+ /// a different operation. Attempting to then reuse that same <see cref="ValueTask"/> results in undefined behavior.
+ /// </item>
+ /// <item>
+ /// Do not attempt to add multiple continuations to the same <see cref="ValueTask"/>. While this might work if the
+ /// <see cref="ValueTask"/> wraps a <code>T</code> or a <see cref="Task"/>, it may not work if the <see cref="ValueTask"/>
+ /// was constructed from an <see cref="IValueTaskSource"/>.
+ /// </item>
+ /// <item>
+ /// Some operations that return a <see cref="ValueTask"/> may invalidate it based on some subsequent operation being performed.
+ /// Unless otherwise documented, assume that a <see cref="ValueTask"/> should be awaited prior to performing any additional operations
+ /// on the instance from which it was retrieved.
+ /// </item>
+ /// </list>
/// </remarks>
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder))]
[StructLayout(LayoutKind.Auto)]
public readonly struct ValueTask : IEquatable<ValueTask>
{
+ /// <summary>A task canceled using `new CancellationToken(true)`.</summary>
+ private static readonly Task s_canceledTask =
+#if netstandard
+ Task.Delay(Timeout.Infinite, new CancellationToken(canceled: true));
+#else
+ Task.FromCanceled(new CancellationToken(canceled: true));
+#endif
+ /// <summary>A successfully completed task.</summary>
internal static Task CompletedTask
#if netstandard
{ get; } = Task.Delay(0);
@@ -34,10 +76,11 @@ namespace System.Threading.Tasks
/// <summary>null if representing a successful synchronous completion, otherwise a <see cref="Task"/> or a <see cref="IValueTaskSource"/>.</summary>
internal readonly object _obj;
- /// <summary>Flags providing additional details about the ValueTask's contents and behavior.</summary>
- internal readonly ValueTaskFlags _flags;
/// <summary>Opaque value passed through to the <see cref="IValueTaskSource"/>.</summary>
internal readonly short _token;
+ /// <summary>true to continue on the capture context; otherwise, true.</summary>
+ /// <remarks>Stored in the <see cref="ValueTask"/> rather than in the configured awaiter to utilize otherwise padding space.</remarks>
+ internal readonly bool _continueOnCapturedContext;
// An instance created with the default ctor (a zero init'd struct) represents a synchronously, successfully completed operation.
@@ -53,7 +96,7 @@ namespace System.Threading.Tasks
_obj = task;
- _flags = ValueTaskFlags.ObjectIsTask;
+ _continueOnCapturedContext = true;
_token = 0;
}
@@ -71,51 +114,15 @@ namespace System.Threading.Tasks
_obj = source;
_token = token;
- _flags = 0;
+ _continueOnCapturedContext = true;
}
- /// <summary>Non-verified initialization of the struct to the specified values.</summary>
- /// <param name="obj">The object.</param>
- /// <param name="token">The token.</param>
- /// <param name="flags">The flags.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private ValueTask(object obj, short token, ValueTaskFlags flags)
+ private ValueTask(object obj, short token, bool continueOnCapturedContext)
{
_obj = obj;
_token = token;
- _flags = flags;
- }
-
- /// <summary>Gets whether the contination should be scheduled to the current context.</summary>
- internal bool ContinueOnCapturedContext
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.AvoidCapturedContext) == 0;
- }
-
- /// <summary>Gets whether the object in the <see cref="_obj"/> field is a <see cref="Task"/>.</summary>
- internal bool ObjectIsTask
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.ObjectIsTask) != 0;
- }
-
- /// <summary>Returns the <see cref="Task"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Task UnsafeGetTask()
- {
- Debug.Assert(ObjectIsTask);
- Debug.Assert(_obj is Task);
- return Unsafe.As<Task>(_obj);
- }
-
- /// <summary>Returns the <see cref="IValueTaskSource"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal IValueTaskSource UnsafeGetValueTaskSource()
- {
- Debug.Assert(!ObjectIsTask);
- Debug.Assert(_obj is IValueTaskSource);
- return Unsafe.As<IValueTaskSource>(_obj);
+ _continueOnCapturedContext = continueOnCapturedContext;
}
/// <summary>Returns the hash code for this instance.</summary>
@@ -144,18 +151,26 @@ namespace System.Threading.Tasks
/// It will either return the wrapped task object if one exists, or it'll
/// manufacture a new task object to represent the result.
/// </remarks>
- public Task AsTask() =>
- _obj == null ? ValueTask.CompletedTask :
- ObjectIsTask ? UnsafeGetTask() :
- GetTaskForValueTaskSource();
+ public Task AsTask()
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+ return
+ obj == null ? CompletedTask :
+ obj as Task ??
+ GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource>(obj));
+ }
/// <summary>Gets a <see cref="ValueTask"/> that may be used at any point in the future.</summary>
public ValueTask Preserve() => _obj == null ? this : new ValueTask(AsTask());
/// <summary>Creates a <see cref="Task"/> to represent the <see cref="IValueTaskSource"/>.</summary>
- private Task GetTaskForValueTaskSource()
+ /// <remarks>
+ /// The <see cref="IValueTaskSource"/> is passed in rather than reading and casting <see cref="_obj"/>
+ /// so that the caller can pass in an object it's already validated.
+ /// </remarks>
+ private Task GetTaskForValueTaskSource(IValueTaskSource t)
{
- IValueTaskSource t = UnsafeGetValueTaskSource();
ValueTaskSourceStatus status = t.GetStatus(_token);
if (status != ValueTaskSourceStatus.Pending)
{
@@ -164,7 +179,7 @@ namespace System.Threading.Tasks
// Propagate any exceptions that may have occurred, then return
// an already successfully completed task.
t.GetResult(_token);
- return ValueTask.CompletedTask;
+ return CompletedTask;
// If status is Faulted or Canceled, GetResult should throw. But
// we can't guarantee every implementation will do the "right thing".
@@ -175,22 +190,15 @@ namespace System.Threading.Tasks
{
if (status == ValueTaskSourceStatus.Canceled)
{
-#if netstandard
- var tcs = new TaskCompletionSource<bool>();
- tcs.TrySetCanceled();
- return tcs.Task;
-#else
+#if !netstandard
if (exc is OperationCanceledException oce)
{
var task = new Task<VoidTaskResult>();
task.TrySetCanceled(oce.CancellationToken, oce);
return task;
}
- else
- {
- return Task.FromCanceled(new CancellationToken(true));
- }
#endif
+ return s_canceledTask;
}
else
{
@@ -205,7 +213,7 @@ namespace System.Threading.Tasks
}
}
- var m = new ValueTaskSourceTask(t, _token);
+ var m = new ValueTaskSourceAsTask(t, _token);
return
#if netstandard
m.Task;
@@ -215,7 +223,7 @@ namespace System.Threading.Tasks
}
/// <summary>Type used to create a <see cref="Task"/> to represent a <see cref="IValueTaskSource"/>.</summary>
- private sealed class ValueTaskSourceTask :
+ private sealed class ValueTaskSourceAsTask :
#if netstandard
TaskCompletionSource<bool>
#else
@@ -224,7 +232,7 @@ namespace System.Threading.Tasks
{
private static readonly Action<object> s_completionAction = state =>
{
- if (!(state is ValueTaskSourceTask vtst) ||
+ if (!(state is ValueTaskSourceAsTask vtst) ||
!(vtst._source is IValueTaskSource source))
{
// This could only happen if the IValueTaskSource passed the wrong state
@@ -270,7 +278,7 @@ namespace System.Threading.Tasks
/// <summary>The token to pass through to operations on <see cref="_source"/></summary>
private readonly short _token;
- public ValueTaskSourceTask(IValueTaskSource source, short token)
+ public ValueTaskSourceAsTask(IValueTaskSource source, short token)
{
_token = token;
_source = source;
@@ -282,30 +290,73 @@ namespace System.Threading.Tasks
public bool IsCompleted
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _obj == null || (ObjectIsTask ? UnsafeGetTask().IsCompleted : UnsafeGetValueTaskSource().GetStatus(_token) != ValueTaskSourceStatus.Pending);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task t)
+ {
+ return t.IsCompleted;
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask"/> represents a successfully completed operation.</summary>
public bool IsCompletedSuccessfully
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get =>
- _obj == null ||
- (ObjectIsTask ?
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task t)
+ {
+ return
#if netstandard
- UnsafeTask.Status == TaskStatus.RanToCompletion :
+ t.Status == TaskStatus.RanToCompletion;
#else
- UnsafeGetTask().IsCompletedSuccessfully :
+ t.IsCompletedSuccessfully;
#endif
- UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Succeeded);
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask"/> represents a failed operation.</summary>
public bool IsFaulted
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsFaulted : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Faulted);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task t)
+ {
+ return t.IsFaulted;
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask"/> represents a canceled operation.</summary>
@@ -316,9 +367,23 @@ namespace System.Threading.Tasks
/// </remarks>
public bool IsCanceled
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsCanceled : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Canceled);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task t)
+ {
+ return t.IsCanceled;
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled;
+ }
}
/// <summary>Throws the exception that caused the <see cref="ValueTask"/> to fail. If it completed successfully, nothing is thrown.</summary>
@@ -326,19 +391,22 @@ namespace System.Threading.Tasks
[StackTraceHidden]
internal void ThrowIfCompletedUnsuccessfully()
{
- if (_obj != null)
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj != null)
{
- if (ObjectIsTask)
+ if (obj is Task t)
{
#if netstandard
- UnsafeTask.GetAwaiter().GetResult();
+ t.GetAwaiter().GetResult();
#else
- TaskAwaiter.ValidateEnd(UnsafeGetTask());
+ TaskAwaiter.ValidateEnd(t);
#endif
}
else
{
- UnsafeGetValueTaskSource().GetResult(_token);
+ Unsafe.As<IValueTaskSource>(obj).GetResult(_token);
}
}
}
@@ -351,34 +419,51 @@ namespace System.Threading.Tasks
/// true to attempt to marshal the continuation back to the captured context; otherwise, false.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
- {
- // TODO: Simplify once https://github.com/dotnet/coreclr/pull/16138 is fixed.
- bool avoidCapture = !continueOnCapturedContext;
- return new ConfiguredValueTaskAwaitable(new ValueTask(_obj, _token, _flags | Unsafe.As<bool, ValueTaskFlags>(ref avoidCapture)));
- }
+ public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) =>
+ new ConfiguredValueTaskAwaitable(new ValueTask(_obj, _token, continueOnCapturedContext));
}
/// <summary>Provides a value type that can represent a synchronously available value or a task object.</summary>
/// <typeparam name="TResult">Specifies the type of the result.</typeparam>
/// <remarks>
- /// <see cref="ValueTask{TResult}"/>s are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task"/>
- /// should be extracted using <see cref="AsTask"/> or <see cref="Preserve"/>. Such operations might include caching an instance to
- /// be awaited later, registering multiple continuations with a single operation, awaiting the same task multiple times, and using
- /// combinators over multiple operations.
+ /// <see cref="ValueTask{TResult}"/> instances are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task{TResult}"/>
+ /// should be extracted using <see cref="AsTask"/>. Such operations might include caching a task instance to be awaited later,
+ /// registering multiple continuations with a single task, awaiting the same task multiple times, and using combinators over
+ /// multiple operations:
+ /// <list type="bullet">
+ /// <item>
+ /// Once the result of a <see cref="ValueTask{TResult}"/> instance has been retrieved, do not attempt to retrieve it again.
+ /// <see cref="ValueTask{TResult}"/> instances may be backed by <see cref="IValueTaskSource{TResult}"/> instances that are reusable, and such
+ /// instances may use the act of retrieving the instances result as a notification that the instance may now be reused for
+ /// a different operation. Attempting to then reuse that same <see cref="ValueTask{TResult}"/> results in undefined behavior.
+ /// </item>
+ /// <item>
+ /// Do not attempt to add multiple continuations to the same <see cref="ValueTask{TResult}"/>. While this might work if the
+ /// <see cref="ValueTask{TResult}"/> wraps a <code>T</code> or a <see cref="Task{TResult}"/>, it may not work if the <see cref="Task{TResult}"/>
+ /// was constructed from an <see cref="IValueTaskSource{TResult}"/>.
+ /// </item>
+ /// <item>
+ /// Some operations that return a <see cref="ValueTask{TResult}"/> may invalidate it based on some subsequent operation being performed.
+ /// Unless otherwise documented, assume that a <see cref="ValueTask{TResult}"/> should be awaited prior to performing any additional operations
+ /// on the instance from which it was retrieved.
+ /// </item>
+ /// </list>
/// </remarks>
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
[StructLayout(LayoutKind.Auto)]
public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
{
+ /// <summary>A task canceled using `new CancellationToken(true)`. Lazily created only when first needed.</summary>
+ private static Task<TResult> s_canceledTask;
/// <summary>null if <see cref="_result"/> has the result, otherwise a <see cref="Task{TResult}"/> or a <see cref="IValueTaskSource{TResult}"/>.</summary>
internal readonly object _obj;
/// <summary>The result to be used if the operation completed successfully synchronously.</summary>
internal readonly TResult _result;
- /// <summary>Flags providing additional details about the ValueTask's contents and behavior.</summary>
- internal readonly ValueTaskFlags _flags;
/// <summary>Opaque value passed through to the <see cref="IValueTaskSource{TResult}"/>.</summary>
internal readonly short _token;
+ /// <summary>true to continue on the captured context; otherwise, false.</summary>
+ /// <remarks>Stored in the <see cref="ValueTask{TResult}"/> rather than in the configured awaiter to utilize otherwise padding space.</remarks>
+ internal readonly bool _continueOnCapturedContext;
// An instance created with the default ctor (a zero init'd struct) represents a synchronously, successfully completed operation
// with a result of default(TResult).
@@ -391,7 +476,7 @@ namespace System.Threading.Tasks
_result = result;
_obj = null;
- _flags = 0;
+ _continueOnCapturedContext = true;
_token = 0;
}
@@ -408,7 +493,7 @@ namespace System.Threading.Tasks
_obj = task;
_result = default;
- _flags = ValueTaskFlags.ObjectIsTask;
+ _continueOnCapturedContext = true;
_token = 0;
}
@@ -427,54 +512,23 @@ namespace System.Threading.Tasks
_token = token;
_result = default;
- _flags = 0;
+ _continueOnCapturedContext = true;
}
/// <summary>Non-verified initialization of the struct to the specified values.</summary>
/// <param name="obj">The object.</param>
/// <param name="result">The result.</param>
/// <param name="token">The token.</param>
- /// <param name="flags">The flags.</param>
+ /// <param name="continueOnCapturedContext">true to continue on captured context; otherwise, false.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private ValueTask(object obj, TResult result, short token, ValueTaskFlags flags)
+ private ValueTask(object obj, TResult result, short token, bool continueOnCapturedContext)
{
_obj = obj;
_result = result;
_token = token;
- _flags = flags;
- }
-
- /// <summary>Gets whether the contination should be scheduled to the current context.</summary>
- internal bool ContinueOnCapturedContext
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.AvoidCapturedContext) == 0;
- }
-
- /// <summary>Gets whether the object in the <see cref="_obj"/> field is a <see cref="Task{TResult}"/>.</summary>
- internal bool ObjectIsTask
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.ObjectIsTask) != 0;
+ _continueOnCapturedContext = continueOnCapturedContext;
}
- /// <summary>Returns the <see cref="Task{TResult}"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Task<TResult> UnsafeGetTask()
- {
- Debug.Assert(ObjectIsTask);
- Debug.Assert(_obj is Task<TResult>);
- return Unsafe.As<Task<TResult>>(_obj);
- }
-
- /// <summary>Returns the <see cref="IValueTaskSource{TResult}"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal IValueTaskSource<TResult> UnsafeGetValueTaskSource()
- {
- Debug.Assert(!ObjectIsTask);
- Debug.Assert(_obj is IValueTaskSource<TResult>);
- return Unsafe.As<IValueTaskSource<TResult>>(_obj);
- }
/// <summary>Returns the hash code for this instance.</summary>
public override int GetHashCode() =>
@@ -508,23 +562,39 @@ namespace System.Threading.Tasks
/// It will either return the wrapped task object if one exists, or it'll
/// manufacture a new task object to represent the result.
/// </remarks>
- public Task<TResult> AsTask() =>
- _obj == null ?
+ public Task<TResult> AsTask()
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return
#if netstandard
- Task.FromResult(_result) :
+ Task.FromResult(_result);
#else
- AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result) :
+ AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
#endif
- ObjectIsTask ? UnsafeGetTask() :
- GetTaskForValueTaskSource();
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t;
+ }
+
+ return GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource<TResult>>(obj));
+ }
/// <summary>Gets a <see cref="ValueTask{TResult}"/> that may be used at any point in the future.</summary>
public ValueTask<TResult> Preserve() => _obj == null ? this : new ValueTask<TResult>(AsTask());
/// <summary>Creates a <see cref="Task{TResult}"/> to represent the <see cref="IValueTaskSource{TResult}"/>.</summary>
- private Task<TResult> GetTaskForValueTaskSource()
+ /// <remarks>
+ /// The <see cref="IValueTaskSource{TResult}"/> is passed in rather than reading and casting <see cref="_obj"/>
+ /// so that the caller can pass in an object it's already validated.
+ /// </remarks>
+ private Task<TResult> GetTaskForValueTaskSource(IValueTaskSource<TResult> t)
{
- IValueTaskSource<TResult> t = UnsafeGetValueTaskSource();
ValueTaskSourceStatus status = t.GetStatus(_token);
if (status != ValueTaskSourceStatus.Pending)
{
@@ -548,22 +618,29 @@ namespace System.Threading.Tasks
{
if (status == ValueTaskSourceStatus.Canceled)
{
-#if netstandard
- var tcs = new TaskCompletionSource<TResult>();
- tcs.TrySetCanceled();
- return tcs.Task;
-#else
+#if !netstandard
if (exc is OperationCanceledException oce)
{
var task = new Task<TResult>();
task.TrySetCanceled(oce.CancellationToken, oce);
return task;
}
- else
+#endif
+
+ Task<TResult> canceledTask = s_canceledTask;
+ if (canceledTask == null)
{
- return Task.FromCanceled<TResult>(new CancellationToken(true));
- }
+#if netstandard
+ var tcs = new TaskCompletionSource<TResult>();
+ tcs.TrySetCanceled();
+ canceledTask = tcs.Task;
+#else
+ canceledTask = Task.FromCanceled<TResult>(new CancellationToken(true));
#endif
+ // Benign race condition to initialize cached task, as identity doesn't matter.
+ s_canceledTask = canceledTask;
+ }
+ return canceledTask;
}
else
{
@@ -578,7 +655,7 @@ namespace System.Threading.Tasks
}
}
- var m = new ValueTaskSourceTask(t, _token);
+ var m = new ValueTaskSourceAsTask(t, _token);
return
#if netstandard
m.Task;
@@ -588,7 +665,7 @@ namespace System.Threading.Tasks
}
/// <summary>Type used to create a <see cref="Task{TResult}"/> to represent a <see cref="IValueTaskSource{TResult}"/>.</summary>
- private sealed class ValueTaskSourceTask :
+ private sealed class ValueTaskSourceAsTask :
#if netstandard
TaskCompletionSource<TResult>
#else
@@ -597,7 +674,7 @@ namespace System.Threading.Tasks
{
private static readonly Action<object> s_completionAction = state =>
{
- if (!(state is ValueTaskSourceTask vtst) ||
+ if (!(state is ValueTaskSourceAsTask vtst) ||
!(vtst._source is IValueTaskSource<TResult> source))
{
// This could only happen if the IValueTaskSource<TResult> passed the wrong state
@@ -642,7 +719,7 @@ namespace System.Threading.Tasks
/// <summary>The token to pass through to operations on <see cref="_source"/></summary>
private readonly short _token;
- public ValueTaskSourceTask(IValueTaskSource<TResult> source, short token)
+ public ValueTaskSourceAsTask(IValueTaskSource<TResult> source, short token)
{
_source = source;
_token = token;
@@ -654,30 +731,73 @@ namespace System.Threading.Tasks
public bool IsCompleted
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _obj == null || (ObjectIsTask ? UnsafeGetTask().IsCompleted : UnsafeGetValueTaskSource().GetStatus(_token) != ValueTaskSourceStatus.Pending);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t.IsCompleted;
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a successfully completed operation.</summary>
public bool IsCompletedSuccessfully
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get =>
- _obj == null ||
- (ObjectIsTask ?
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return
#if netstandard
- UnsafeTask.Status == TaskStatus.RanToCompletion :
+ t.Status == TaskStatus.RanToCompletion;
#else
- UnsafeGetTask().IsCompletedSuccessfully :
+ t.IsCompletedSuccessfully;
#endif
- UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Succeeded);
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a failed operation.</summary>
public bool IsFaulted
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsFaulted : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Faulted);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t.IsFaulted;
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a canceled operation.</summary>
@@ -688,9 +808,23 @@ namespace System.Threading.Tasks
/// </remarks>
public bool IsCanceled
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsCanceled : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Canceled);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t.IsCanceled;
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled;
+ }
}
/// <summary>Gets the result.</summary>
@@ -699,23 +833,25 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- if (_obj == null)
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
{
return _result;
}
- if (ObjectIsTask)
+ if (obj is Task<TResult> t)
{
#if netstandard
- return UnsafeTask.GetAwaiter().GetResult();
+ return t.GetAwaiter().GetResult();
#else
- Task<TResult> t = UnsafeGetTask();
TaskAwaiter.ValidateEnd(t);
return t.ResultOnSuccess;
#endif
}
- return UnsafeGetValueTaskSource().GetResult(_token);
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetResult(_token);
}
}
@@ -728,12 +864,8 @@ namespace System.Threading.Tasks
/// true to attempt to marshal the continuation back to the captured context; otherwise, false.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext)
- {
- // TODO: Simplify once https://github.com/dotnet/coreclr/pull/16138 is fixed.
- bool avoidCapture = !continueOnCapturedContext;
- return new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, _flags | Unsafe.As<bool, ValueTaskFlags>(ref avoidCapture)));
- }
+ public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) =>
+ new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, continueOnCapturedContext));
/// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
public override string ToString()
@@ -750,26 +882,4 @@ namespace System.Threading.Tasks
return string.Empty;
}
}
-
- /// <summary>Internal flags used in the implementation of <see cref="ValueTask"/> and <see cref="ValueTask{TResult}"/>.</summary>
- [Flags]
- internal enum ValueTaskFlags : byte
- {
- /// <summary>
- /// Indicates that context (e.g. SynchronizationContext) should not be captured when adding
- /// a continuation.
- /// </summary>
- /// <remarks>
- /// The value here must be 0x1, to match the value of a true Boolean reinterpreted as a byte.
- /// This only has meaning when awaiting a ValueTask, with ConfigureAwait creating a new
- /// ValueTask setting or not setting this flag appropriately.
- /// </remarks>
- AvoidCapturedContext = 0x1,
-
- /// <summary>
- /// Indicates that the ValueTask's object field stores a Task. This is used to avoid
- /// a type check on whatever is stored in the object field.
- /// </summary>
- ObjectIsTask = 0x2
- }
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs
new file mode 100644
index 000000000..13fa1e91b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs
@@ -0,0 +1,45 @@
+// 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.Runtime.Serialization;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// An exception class to indicate that the thread was interrupted from a waiting state.
+ /// </summary>
+ [Serializable]
+#if !MONO
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public class ThreadInterruptedException : SystemException
+ {
+ public ThreadInterruptedException() : base(
+#if CORECLR
+ GetMessageFromNativeResources(ExceptionMessageKind.ThreadInterrupted)
+#else
+ SR.Threading_ThreadInterrupted
+#endif
+ )
+ {
+ HResult = HResults.COR_E_THREADINTERRUPTED;
+ }
+
+ public ThreadInterruptedException(string message)
+ : base(message)
+ {
+ HResult = HResults.COR_E_THREADINTERRUPTED;
+ }
+
+ public ThreadInterruptedException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ HResult = HResults.COR_E_THREADINTERRUPTED;
+ }
+
+ protected ThreadInterruptedException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs
new file mode 100644
index 000000000..9f4beae9c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs
@@ -0,0 +1,781 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+
+// A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing
+// thread; this provides an alternative to using a ThreadStatic static variable and having
+// to check the variable prior to every access to see if it's been initialized.
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Provides thread-local storage of data.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of data stored per-thread.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// With the exception of <see cref="Dispose()"/>, all public and protected members of
+ /// <see cref="ThreadLocal{T}"/> are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </para>
+ /// </remarks>
+ [DebuggerTypeProxy(typeof(SystemThreading_ThreadLocalDebugView<>))]
+ [DebuggerDisplay("IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")]
+ public class ThreadLocal<T> : IDisposable
+ {
+ // a delegate that returns the created value, if null the created value will be default(T)
+ private Func<T> _valueFactory;
+
+ // ts_slotArray is a table of thread-local values for all ThreadLocal<T> instances
+ //
+ // So, when a thread reads ts_slotArray, it gets back an array of *all* ThreadLocal<T> values for this thread and this T.
+ // The slot relevant to this particular ThreadLocal<T> instance is determined by the _idComplement instance field stored in
+ // the ThreadLocal<T> instance.
+ [ThreadStatic]
+ private static LinkedSlotVolatile[] ts_slotArray;
+
+ [ThreadStatic]
+ private static FinalizationHelper ts_finalizationHelper;
+
+ // Slot ID of this ThreadLocal<> instance. We store a bitwise complement of the ID (that is ~ID), which allows us to distinguish
+ // between the case when ID is 0 and an incompletely initialized object, either due to a thread abort in the constructor, or
+ // possibly due to a memory model issue in user code.
+ private int _idComplement;
+
+ // This field is set to true when the constructor completes. That is helpful for recognizing whether a constructor
+ // threw an exception - either due to invalid argument or due to a thread abort. Finally, the field is set to false
+ // when the instance is disposed.
+ private volatile bool _initialized;
+
+ // IdManager assigns and reuses slot IDs. Additionally, the object is also used as a global lock.
+ private static IdManager s_idManager = new IdManager();
+
+ // A linked list of all values associated with this ThreadLocal<T> instance.
+ // We create a dummy head node. That allows us to remove any (non-dummy) node without having to locate the m_linkedSlot field.
+ private LinkedSlot _linkedSlot = new LinkedSlot(null);
+
+ // Whether the Values property is supported
+ private bool _trackAllValues;
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance.
+ /// </summary>
+ public ThreadLocal()
+ {
+ Initialize(null, false);
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance.
+ /// </summary>
+ /// <param name="trackAllValues">Whether to track all values set on the instance and expose them through the Values property.</param>
+ public ThreadLocal(bool trackAllValues)
+ {
+ Initialize(null, trackAllValues);
+ }
+
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance with the
+ /// specified <paramref name="valueFactory"/> function.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
+ /// an attempt is made to retrieve <see cref="Value"/> without it having been previously initialized.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="valueFactory"/> is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ public ThreadLocal(Func<T> valueFactory)
+ {
+ if (valueFactory == null)
+ throw new ArgumentNullException(nameof(valueFactory));
+
+ Initialize(valueFactory, false);
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance with the
+ /// specified <paramref name="valueFactory"/> function.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
+ /// an attempt is made to retrieve <see cref="Value"/> without it having been previously initialized.
+ /// </param>
+ /// <param name="trackAllValues">Whether to track all values set on the instance and expose them via the Values property.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="valueFactory"/> is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ public ThreadLocal(Func<T> valueFactory, bool trackAllValues)
+ {
+ if (valueFactory == null)
+ throw new ArgumentNullException(nameof(valueFactory));
+
+ Initialize(valueFactory, trackAllValues);
+ }
+
+ private void Initialize(Func<T> valueFactory, bool trackAllValues)
+ {
+ _valueFactory = valueFactory;
+ _trackAllValues = trackAllValues;
+
+ // Assign the ID and mark the instance as initialized. To avoid leaking IDs, we assign the ID and set _initialized
+ // in a finally block, to avoid a thread abort in between the two statements.
+ try { }
+ finally
+ {
+ _idComplement = ~s_idManager.GetId();
+
+ // As the last step, mark the instance as fully initialized. (Otherwise, if _initialized=false, we know that an exception
+ // occurred in the constructor.)
+ _initialized = true;
+ }
+ }
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.ThreadLocal{T}" /> instance.
+ /// </summary>
+ ~ThreadLocal()
+ {
+ // finalizer to return the type combination index to the pool
+ Dispose(false);
+ }
+
+ #region IDisposable Members
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.ThreadLocal{T}" /> instance.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="T:System.Threading.ThreadLocal{T}"/>, this method is not thread-safe.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.ThreadLocal{T}" /> instance.
+ /// </summary>
+ /// <param name="disposing">
+ /// A Boolean value that indicates whether this method is being called due to a call to <see cref="Dispose()"/>.
+ /// </param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="T:System.Threading.ThreadLocal{T}"/>, this method is not thread-safe.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ int id;
+
+ lock (s_idManager)
+ {
+ id = ~_idComplement;
+ _idComplement = 0;
+
+ if (id < 0 || !_initialized)
+ {
+ Debug.Assert(id >= 0 || !_initialized, "expected id >= 0 if initialized");
+
+ // Handle double Dispose calls or disposal of an instance whose constructor threw an exception.
+ return;
+ }
+ _initialized = false;
+
+ for (LinkedSlot linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
+ {
+ LinkedSlotVolatile[] slotArray = linkedSlot._slotArray;
+
+ if (slotArray == null)
+ {
+ // The thread that owns this slotArray has already finished.
+ continue;
+ }
+
+ // Remove the reference from the LinkedSlot to the slot table.
+ linkedSlot._slotArray = null;
+
+ // And clear the references from the slot table to the linked slot and the value so that
+ // both can get garbage collected.
+ slotArray[id].Value._value = default;
+ slotArray[id].Value = null;
+ }
+ }
+ _linkedSlot = null;
+ s_idManager.ReturnId(id);
+ }
+
+ #endregion
+
+ /// <summary>Creates and returns a string representation of this instance for the current thread.</summary>
+ /// <returns>The result of calling <see cref="System.Object.ToString"/> on the <see cref="Value"/>.</returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <see cref="Value"/> for the current thread is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The initialization function referenced <see cref="Value"/> in an improper manner.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling this method forces initialization for the current thread, as is the
+ /// case with accessing <see cref="Value"/> directly.
+ /// </remarks>
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
+
+ /// <summary>
+ /// Gets or sets the value of this instance for the current thread.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The initialization function referenced <see cref="Value"/> in an improper manner.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ /// <remarks>
+ /// If this instance was not previously initialized for the current thread,
+ /// accessing <see cref="Value"/> will attempt to initialize it. If an initialization function was
+ /// supplied during the construction, that initialization will happen by invoking the function
+ /// to retrieve the initial value for <see cref="Value"/>. Otherwise, the default value of
+ /// <typeparamref name="T"/> will be used.
+ /// </remarks>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ public T Value
+ {
+ get
+ {
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ LinkedSlot slot;
+ int id = ~_idComplement;
+
+ //
+ // Attempt to get the value using the fast path
+ //
+ if (slotArray != null // Has the slot array been initialized?
+ && id >= 0 // Is the ID non-negative (i.e., instance is not disposed)?
+ && id < slotArray.Length // Is the table large enough?
+ && (slot = slotArray[id].Value) != null // Has a LinkedSlot object has been allocated for this ID?
+ && _initialized // Has the instance *still* not been disposed (important for a race condition with Dispose)?
+ )
+ {
+ // We verified that the instance has not been disposed *after* we got a reference to the slot.
+ // This guarantees that we have a reference to the right slot.
+ //
+ // Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
+ // will not be reordered before the read of slotArray[id].
+ return slot._value;
+ }
+
+ return GetValueSlow();
+ }
+ set
+ {
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ LinkedSlot slot;
+ int id = ~_idComplement;
+
+ // Attempt to set the value using the fast path
+ if (slotArray != null // Has the slot array been initialized?
+ && id >= 0 // Is the ID non-negative (i.e., instance is not disposed)?
+ && id < slotArray.Length // Is the table large enough?
+ && (slot = slotArray[id].Value) != null // Has a LinkedSlot object has been allocated for this ID?
+ && _initialized // Has the instance *still* not been disposed (important for a race condition with Dispose)?
+ )
+ {
+ // We verified that the instance has not been disposed *after* we got a reference to the slot.
+ // This guarantees that we have a reference to the right slot.
+ //
+ // Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
+ // will not be reordered before the read of slotArray[id].
+ slot._value = value;
+ }
+ else
+ {
+ SetValueSlow(value, slotArray);
+ }
+ }
+ }
+
+ private T GetValueSlow()
+ {
+ // If the object has been disposed, the id will be -1.
+ int id = ~_idComplement;
+ if (id < 0)
+ {
+ throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+ }
+
+ Debugger.NotifyOfCrossThreadDependency();
+
+ // Determine the initial value
+ T value;
+ if (_valueFactory == null)
+ {
+ value = default;
+ }
+ else
+ {
+ value = _valueFactory();
+
+ if (IsValueCreated)
+ {
+ throw new InvalidOperationException(SR.ThreadLocal_Value_RecursiveCallsToValue);
+ }
+ }
+
+ // Since the value has been previously uninitialized, we also need to set it (according to the ThreadLocal semantics).
+ Value = value;
+ return value;
+ }
+
+ private void SetValueSlow(T value, LinkedSlotVolatile[] slotArray)
+ {
+ int id = ~_idComplement;
+
+ // If the object has been disposed, id will be -1.
+ if (id < 0)
+ {
+ throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+ }
+
+ // If a slot array has not been created on this thread yet, create it.
+ if (slotArray == null)
+ {
+ slotArray = new LinkedSlotVolatile[GetNewTableSize(id + 1)];
+ ts_finalizationHelper = new FinalizationHelper(slotArray, _trackAllValues);
+ ts_slotArray = slotArray;
+ }
+
+ // If the slot array is not big enough to hold this ID, increase the table size.
+ if (id >= slotArray.Length)
+ {
+ GrowTable(ref slotArray, id + 1);
+ ts_finalizationHelper.SlotArray = slotArray;
+ ts_slotArray = slotArray;
+ }
+
+ // If we are using the slot in this table for the first time, create a new LinkedSlot and add it into
+ // the linked list for this ThreadLocal instance.
+ if (slotArray[id].Value == null)
+ {
+ CreateLinkedSlot(slotArray, id, value);
+ }
+ else
+ {
+ // Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
+ // that follows will not be reordered before the read of slotArray[id].
+ LinkedSlot slot = slotArray[id].Value;
+
+ // It is important to verify that the ThreadLocal instance has not been disposed. The check must come
+ // after capturing slotArray[id], but before assigning the value into the slot. This ensures that
+ // if this ThreadLocal instance was disposed on another thread and another ThreadLocal instance was
+ // created, we definitely won't assign the value into the wrong instance.
+
+ if (!_initialized)
+ {
+ throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+ }
+
+ slot._value = value;
+ }
+ }
+
+ /// <summary>
+ /// Creates a LinkedSlot and inserts it into the linked list for this ThreadLocal instance.
+ /// </summary>
+ private void CreateLinkedSlot(LinkedSlotVolatile[] slotArray, int id, T value)
+ {
+ // Create a LinkedSlot
+ var linkedSlot = new LinkedSlot(slotArray);
+
+ // Insert the LinkedSlot into the linked list maintained by this ThreadLocal<> instance and into the slot array
+ lock (s_idManager)
+ {
+ // Check that the instance has not been disposed. It is important to check this under a lock, since
+ // Dispose also executes under a lock.
+ if (!_initialized)
+ {
+ throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+ }
+
+ LinkedSlot firstRealNode = _linkedSlot._next;
+
+ // Insert linkedSlot between nodes m_linkedSlot and firstRealNode.
+ // (_linkedSlot is the dummy head node that should always be in the front.)
+ linkedSlot._next = firstRealNode;
+ linkedSlot._previous = _linkedSlot;
+ linkedSlot._value = value;
+
+ if (firstRealNode != null)
+ {
+ firstRealNode._previous = linkedSlot;
+ }
+ _linkedSlot._next = linkedSlot;
+
+ // Assigning the slot under a lock prevents a race condition with Dispose (dispose also acquires the lock).
+ // Otherwise, it would be possible that the ThreadLocal instance is disposed, another one gets created
+ // with the same ID, and the write would go to the wrong instance.
+ slotArray[id].Value = linkedSlot;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list for all of the values currently stored by all of the threads that have accessed this instance.
+ /// </summary>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ public IList<T> Values
+ {
+ get
+ {
+ if (!_trackAllValues)
+ {
+ throw new InvalidOperationException(SR.ThreadLocal_ValuesNotAvailable);
+ }
+
+ var list = GetValuesAsList(); // returns null if disposed
+ if (list == null) throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+ return list;
+ }
+ }
+
+ /// <summary>Gets all of the threads' values in a list.</summary>
+ private List<T> GetValuesAsList()
+ {
+ List<T> valueList = new List<T>();
+ int id = ~_idComplement;
+ if (id == -1)
+ {
+ return null;
+ }
+
+ // Walk over the linked list of slots and gather the values associated with this ThreadLocal instance.
+ for (LinkedSlot linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
+ {
+ // We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
+ // objects will never be assigned to another ThreadLocal instance.
+ valueList.Add(linkedSlot._value);
+ }
+
+ return valueList;
+ }
+
+ /// <summary>Gets the number of threads that have data in this instance.</summary>
+ private int ValuesCountForDebugDisplay
+ {
+ get
+ {
+ int count = 0;
+ for (LinkedSlot linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
+ {
+ count++;
+ }
+ return count;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether <see cref="Value"/> is initialized on the current thread.
+ /// </summary>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ public bool IsValueCreated
+ {
+ get
+ {
+ int id = ~_idComplement;
+ if (id < 0)
+ {
+ throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
+ }
+
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ return slotArray != null && id < slotArray.Length && slotArray[id].Value != null;
+ }
+ }
+
+
+ /// <summary>Gets the value of the ThreadLocal&lt;T&gt; for debugging display purposes. It takes care of getting
+ /// the value for the current thread in the ThreadLocal mode.</summary>
+ internal T ValueForDebugDisplay
+ {
+ get
+ {
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ int id = ~_idComplement;
+
+ LinkedSlot slot;
+ if (slotArray == null || id >= slotArray.Length || (slot = slotArray[id].Value) == null || !_initialized)
+ return default;
+ return slot._value;
+ }
+ }
+
+ /// <summary>Gets the values of all threads that accessed the ThreadLocal&lt;T&gt;.</summary>
+ internal List<T> ValuesForDebugDisplay // same as Values property, but doesn't throw if disposed
+ {
+ get { return GetValuesAsList(); }
+ }
+
+ /// <summary>
+ /// Resizes a table to a certain length (or larger).
+ /// </summary>
+ private void GrowTable(ref LinkedSlotVolatile[] table, int minLength)
+ {
+ Debug.Assert(table.Length < minLength);
+
+ // Determine the size of the new table and allocate it.
+ int newLen = GetNewTableSize(minLength);
+ LinkedSlotVolatile[] newTable = new LinkedSlotVolatile[newLen];
+
+ //
+ // The lock is necessary to avoid a race with ThreadLocal.Dispose. GrowTable has to point all
+ // LinkedSlot instances referenced in the old table to reference the new table. Without locking,
+ // Dispose could use a stale SlotArray reference and clear out a slot in the old array only, while
+ // the value continues to be referenced from the new (larger) array.
+ //
+ lock (s_idManager)
+ {
+ for (int i = 0; i < table.Length; i++)
+ {
+ LinkedSlot linkedSlot = table[i].Value;
+ if (linkedSlot != null && linkedSlot._slotArray != null)
+ {
+ linkedSlot._slotArray = newTable;
+ newTable[i] = table[i];
+ }
+ }
+ }
+
+ table = newTable;
+ }
+
+ /// <summary>
+ /// Chooses the next larger table size
+ /// </summary>
+ private static int GetNewTableSize(int minSize)
+ {
+ if ((uint)minSize > Array.MaxArrayLength)
+ {
+ // Intentionally return a value that will result in an OutOfMemoryException
+ return int.MaxValue;
+ }
+ Debug.Assert(minSize > 0);
+
+ //
+ // Round up the size to the next power of 2
+ //
+ // The algorithm takes three steps:
+ // input -> subtract one -> propagate 1-bits to the right -> add one
+ //
+ // Let's take a look at the 3 steps in both interesting cases: where the input
+ // is (Example 1) and isn't (Example 2) a power of 2.
+ //
+ // Example 1: 100000 -> 011111 -> 011111 -> 100000
+ // Example 2: 011010 -> 011001 -> 011111 -> 100000
+ //
+ int newSize = minSize;
+
+ // Step 1: Decrement
+ newSize--;
+
+ // Step 2: Propagate 1-bits to the right.
+ newSize |= newSize >> 1;
+ newSize |= newSize >> 2;
+ newSize |= newSize >> 4;
+ newSize |= newSize >> 8;
+ newSize |= newSize >> 16;
+
+ // Step 3: Increment
+ newSize++;
+
+ // Don't set newSize to more than Array.MaxArrayLength
+ if ((uint)newSize > Array.MaxArrayLength)
+ {
+ newSize = Array.MaxArrayLength;
+ }
+
+ return newSize;
+ }
+
+ /// <summary>
+ /// A wrapper struct used as LinkedSlotVolatile[] - an array of LinkedSlot instances, but with volatile semantics
+ /// on array accesses.
+ /// </summary>
+ private struct LinkedSlotVolatile
+ {
+ internal volatile LinkedSlot Value;
+ }
+
+ /// <summary>
+ /// A node in the doubly-linked list stored in the ThreadLocal instance.
+ ///
+ /// The value is stored in one of two places:
+ ///
+ /// 1. If SlotArray is not null, the value is in SlotArray.Table[id]
+ /// 2. If SlotArray is null, the value is in FinalValue.
+ /// </summary>
+ private sealed class LinkedSlot
+ {
+ internal LinkedSlot(LinkedSlotVolatile[] slotArray)
+ {
+ _slotArray = slotArray;
+ }
+
+ // The next LinkedSlot for this ThreadLocal<> instance
+ internal volatile LinkedSlot _next;
+
+ // The previous LinkedSlot for this ThreadLocal<> instance
+ internal volatile LinkedSlot _previous;
+
+ // The SlotArray that stores this LinkedSlot at SlotArray.Table[id].
+ internal volatile LinkedSlotVolatile[] _slotArray;
+
+ // The value for this slot.
+ internal T _value;
+ }
+
+ /// <summary>
+ /// A manager class that assigns IDs to ThreadLocal instances
+ /// </summary>
+ private class IdManager
+ {
+ // The next ID to try
+ private int _nextIdToTry = 0;
+
+ // Stores whether each ID is free or not. Additionally, the object is also used as a lock for the IdManager.
+ private List<bool> _freeIds = new List<bool>();
+
+ internal int GetId()
+ {
+ lock (_freeIds)
+ {
+ int availableId = _nextIdToTry;
+ while (availableId < _freeIds.Count)
+ {
+ if (_freeIds[availableId]) { break; }
+ availableId++;
+ }
+
+ if (availableId == _freeIds.Count)
+ {
+ _freeIds.Add(false);
+ }
+ else
+ {
+ _freeIds[availableId] = false;
+ }
+
+ _nextIdToTry = availableId + 1;
+
+ return availableId;
+ }
+ }
+
+ // Return an ID to the pool
+ internal void ReturnId(int id)
+ {
+ lock (_freeIds)
+ {
+ _freeIds[id] = true;
+ if (id < _nextIdToTry) _nextIdToTry = id;
+ }
+ }
+ }
+
+ /// <summary>
+ /// A class that facilitates ThreadLocal cleanup after a thread exits.
+ ///
+ /// After a thread with an associated thread-local table has exited, the FinalizationHelper
+ /// is responsible for removing back-references to the table. Since an instance of FinalizationHelper
+ /// is only referenced from a single thread-local slot, the FinalizationHelper will be GC'd once
+ /// the thread has exited.
+ ///
+ /// The FinalizationHelper then locates all LinkedSlot instances with back-references to the table
+ /// (all those LinkedSlot instances can be found by following references from the table slots) and
+ /// releases the table so that it can get GC'd.
+ /// </summary>
+ private class FinalizationHelper
+ {
+ internal LinkedSlotVolatile[] SlotArray;
+ private bool _trackAllValues;
+
+ internal FinalizationHelper(LinkedSlotVolatile[] slotArray, bool trackAllValues)
+ {
+ SlotArray = slotArray;
+ _trackAllValues = trackAllValues;
+ }
+
+ ~FinalizationHelper()
+ {
+ LinkedSlotVolatile[] slotArray = SlotArray;
+ Debug.Assert(slotArray != null);
+
+ for (int i = 0; i < slotArray.Length; i++)
+ {
+ LinkedSlot linkedSlot = slotArray[i].Value;
+ if (linkedSlot == null)
+ {
+ // This slot in the table is empty
+ continue;
+ }
+
+ if (_trackAllValues)
+ {
+ // Set the SlotArray field to null to release the slot array.
+ linkedSlot._slotArray = null;
+ }
+ else
+ {
+ // Remove the LinkedSlot from the linked list. Once the FinalizationHelper is done, all back-references to
+ // the table will be have been removed, and so the table can get GC'd.
+ lock (s_idManager)
+ {
+ if (linkedSlot._next != null)
+ {
+ linkedSlot._next._previous = linkedSlot._previous;
+ }
+
+ // Since the list uses a dummy head node, the Previous reference should never be null.
+ Debug.Assert(linkedSlot._previous != null);
+ linkedSlot._previous._next = linkedSlot._next;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>A debugger view of the ThreadLocal&lt;T&gt; to surface additional debugging properties and
+ /// to ensure that the ThreadLocal&lt;T&gt; does not become initialized if it was not already.</summary>
+ internal sealed class SystemThreading_ThreadLocalDebugView<T>
+ {
+ //The ThreadLocal object being viewed.
+ private readonly ThreadLocal<T> _tlocal;
+
+ /// <summary>Constructs a new debugger view object for the provided ThreadLocal object.</summary>
+ /// <param name="tlocal">A ThreadLocal object to browse in the debugger.</param>
+ public SystemThreading_ThreadLocalDebugView(ThreadLocal<T> tlocal)
+ {
+ _tlocal = tlocal;
+ }
+
+ /// <summary>Returns whether the ThreadLocal object is initialized or not.</summary>
+ public bool IsValueCreated => _tlocal.IsValueCreated;
+
+ /// <summary>Returns the value of the ThreadLocal object.</summary>
+ public T Value => _tlocal.ValueForDebugDisplay;
+
+ /// <summary>Return all values for all threads that have accessed this instance.</summary>
+ public List<T> Values => _tlocal.ValuesForDebugDisplay;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs
index 6fc06a851..d9ba48dfc 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs
@@ -26,13 +26,13 @@ namespace System.Threading
HResult = HResults.COR_E_THREADSTATE;
}
- public ThreadStateException(String message)
+ public ThreadStateException(string message)
: base(message)
{
HResult = HResults.COR_E_THREADSTATE;
}
- public ThreadStateException(String message, Exception innerException)
+ public ThreadStateException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_THREADSTATE;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs b/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs
index c96a4d00d..dd3291281 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs
@@ -7,16 +7,16 @@ using System.Diagnostics;
namespace System.Threading
{
/// <summary>
- /// A helper class to capture a start time using Environment.TickCout as a time in milliseconds, also updates a given timeout bu subtracting the current time from
- /// the start time
+ /// A helper class to capture a start time using <see cref="Environment.TickCount"/> as a time in milliseconds.
+ /// Also updates a given timeout by subtracting the current time from the start time.
/// </summary>
internal static class TimeoutHelper
{
/// <summary>
- /// Returns the Environment.TickCount as a start time in milliseconds as a uint, TickCount tools over from positive to negative every ~ 25 days
- /// then ~25 days to back to positive again, uint is sued to ignore the sign and double the range to 50 days
+ /// Returns <see cref="Environment.TickCount"/> as a start time in milliseconds as a <see cref="UInt32"/>.
+ /// <see cref="Environment.TickCount"/> rolls over from positive to negative every ~25 days, then ~25 days to back to positive again.
+ /// <see cref="UInt32"/> is used to ignore the sign and double the range to 50 days.
/// </summary>
- /// <returns></returns>
public static uint GetTime()
{
return (uint)Environment.TickCount;
@@ -27,7 +27,7 @@ namespace System.Threading
/// </summary>
/// <param name="startTime"> The first time (in milliseconds) observed when the wait started</param>
/// <param name="originalWaitMillisecondsTimeout">The original wait timeout in milliseconds</param>
- /// <returns>The new wait time in milliseconds, -1 if the time expired</returns>
+ /// <returns>The new wait time in milliseconds, or -1 if the time expired</returns>
public static int UpdateTimeOut(uint startTime, int originalWaitMillisecondsTimeout)
{
// The function must be called in case the time out is not infinite
@@ -42,7 +42,7 @@ namespace System.Threading
}
// Subtract the elapsed time from the current wait time
- int currentWaitTimeout = originalWaitMillisecondsTimeout - (int)elapsedMilliseconds; ;
+ int currentWaitTimeout = originalWaitMillisecondsTimeout - (int)elapsedMilliseconds;
if (currentWaitTimeout <= 0)
{
return 0;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs b/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
index e60e46d2b..60821542b 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
@@ -15,12 +15,12 @@ namespace System.Threading
HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
- public WaitHandleCannotBeOpenedException(String message) : base(message)
+ public WaitHandleCannotBeOpenedException(string message) : base(message)
{
HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
- public WaitHandleCannotBeOpenedException(String message, Exception innerException) : base(message, innerException)
+ public WaitHandleCannotBeOpenedException(string message, Exception innerException) : base(message, innerException)
{
HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeSpan.cs b/src/System.Private.CoreLib/shared/System/TimeSpan.cs
index 4293ed505..10bdb331b 100644
--- a/src/System.Private.CoreLib/shared/System/TimeSpan.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeSpan.cs
@@ -28,13 +28,13 @@ namespace System
// an appropriate custom ILMarshaler to keep WInRT interop scenarios enabled.
//
[Serializable]
- public struct TimeSpan : IComparable, IComparable<TimeSpan>, IEquatable<TimeSpan>, IFormattable, ISpanFormattable
+ public readonly struct TimeSpan : IComparable, IComparable<TimeSpan>, IEquatable<TimeSpan>, IFormattable, ISpanFormattable
{
public const long TicksPerMillisecond = 10000;
private const double MillisecondsPerTick = 1.0 / TicksPerMillisecond;
public const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
- private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0001
+ private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0000001
public const long TicksPerMinute = TicksPerSecond * 60; // 600,000,000
private const double MinutesPerTick = 1.0 / TicksPerMinute; // 1.6666666666667e-9
@@ -50,22 +50,22 @@ namespace System
private const int MillisPerHour = MillisPerMinute * 60; // 3,600,000
private const int MillisPerDay = MillisPerHour * 24; // 86,400,000
- internal const long MaxSeconds = Int64.MaxValue / TicksPerSecond;
- internal const long MinSeconds = Int64.MinValue / TicksPerSecond;
+ internal const long MaxSeconds = long.MaxValue / TicksPerSecond;
+ internal const long MinSeconds = long.MinValue / TicksPerSecond;
- internal const long MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
- internal const long MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
+ internal const long MaxMilliSeconds = long.MaxValue / TicksPerMillisecond;
+ internal const long MinMilliSeconds = long.MinValue / TicksPerMillisecond;
internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
public static readonly TimeSpan Zero = new TimeSpan(0);
- public static readonly TimeSpan MaxValue = new TimeSpan(Int64.MaxValue);
- public static readonly TimeSpan MinValue = new TimeSpan(Int64.MinValue);
+ public static readonly TimeSpan MaxValue = new TimeSpan(long.MaxValue);
+ public static readonly TimeSpan MinValue = new TimeSpan(long.MinValue);
// internal so that DateTime doesn't have to call an extra get
// method for some arithmetic operations.
- internal long _ticks; // Do not rename (binary serialization)
+ internal readonly long _ticks; // Do not rename (binary serialization)
public TimeSpan(long ticks)
{
@@ -84,7 +84,7 @@ namespace System
public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds)
{
- Int64 totalMilliSeconds = ((Int64)days * 3600 * 24 + (Int64)hours * 3600 + (Int64)minutes * 60 + seconds) * 1000 + milliseconds;
+ long totalMilliSeconds = ((long)days * 3600 * 24 + (long)hours * 3600 + (long)minutes * 60 + seconds) * 1000 + milliseconds;
if (totalMilliSeconds > MaxMilliSeconds || totalMilliSeconds < MinMilliSeconds)
throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
_ticks = (long)totalMilliSeconds * TicksPerMillisecond;
@@ -178,7 +178,7 @@ namespace System
}
// Returns a value less than zero if this object
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null) return 1;
if (!(value is TimeSpan))
@@ -209,7 +209,7 @@ namespace System
return new TimeSpan(_ticks >= 0 ? _ticks : -_ticks);
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
if (value is TimeSpan)
{
@@ -240,11 +240,11 @@ namespace System
private static TimeSpan Interval(double value, int scale)
{
- if (Double.IsNaN(value))
+ if (double.IsNaN(value))
throw new ArgumentException(SR.Arg_CannotBeNaN);
double tmp = value * scale;
double millis = tmp + (value >= 0 ? 0.5 : -0.5);
- if ((millis > Int64.MaxValue / TicksPerMillisecond) || (millis < Int64.MinValue / TicksPerMillisecond))
+ if ((millis > long.MaxValue / TicksPerMillisecond) || (millis < long.MinValue / TicksPerMillisecond))
throw new OverflowException(SR.Overflow_TimeSpanTooLong);
return new TimeSpan((long)millis * TicksPerMillisecond);
}
@@ -305,18 +305,18 @@ namespace System
// See System.Globalization.TimeSpanParse and System.Globalization.TimeSpanFormat
#region ParseAndFormat
- private static void ValidateStyles(TimeSpanStyles style, String parameterName)
+ private static void ValidateStyles(TimeSpanStyles style, string parameterName)
{
if (style != TimeSpanStyles.None && style != TimeSpanStyles.AssumeNegative)
throw new ArgumentException(SR.Argument_InvalidTimeSpanStyles, parameterName);
}
- public static TimeSpan Parse(String s)
+ public static TimeSpan Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
/* Constructs a TimeSpan from a string. Leading and trailing white space characters are allowed. */
return TimeSpanParse.Parse(s, null);
}
- public static TimeSpan Parse(String input, IFormatProvider formatProvider)
+ public static TimeSpan Parse(string input, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
return TimeSpanParse.Parse(input, formatProvider);
@@ -325,18 +325,18 @@ namespace System
{
return TimeSpanParse.Parse(input, formatProvider);
}
- public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider)
+ public static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
return TimeSpanParse.ParseExact(input, format, formatProvider, TimeSpanStyles.None);
}
- public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider)
+ public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None);
}
- public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles)
+ public static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles)
{
ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -349,7 +349,7 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.ParseExact(input, format, formatProvider, styles);
}
- public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
+ public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
{
ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -360,11 +360,11 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles);
}
- public static Boolean TryParse(String s, out TimeSpan result)
+ public static bool TryParse(string s, out TimeSpan result)
{
if (s == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParse(s, null, out result);
@@ -374,11 +374,11 @@ namespace System
return TimeSpanParse.TryParse(s, null, out result);
}
- public static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result)
+ public static bool TryParse(string input, IFormatProvider formatProvider, out TimeSpan result)
{
if (input == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParse(input, formatProvider, out result);
@@ -387,7 +387,7 @@ namespace System
{
return TimeSpanParse.TryParse(input, formatProvider, out result);
}
- public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, out TimeSpan result)
+ public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, out TimeSpan result)
{
if (input == null || format == null)
{
@@ -401,11 +401,11 @@ namespace System
{
return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result);
}
- public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, out TimeSpan result)
+ public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, out TimeSpan result)
{
if (input == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result);
@@ -415,7 +415,7 @@ namespace System
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result);
}
- public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
+ public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
ValidateStyles(styles, nameof(styles));
if (input == null || format == null)
@@ -432,12 +432,12 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result);
}
- public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
+ public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
ValidateStyles(styles, nameof(styles));
if (input == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result);
@@ -448,15 +448,15 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result);
}
- public override String ToString()
+ public override string ToString()
{
- return TimeSpanFormat.Format(this, null, null);
+ return TimeSpanFormat.FormatC(this);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return TimeSpanFormat.Format(this, format, null);
}
- public String ToString(String format, IFormatProvider formatProvider)
+ public string ToString(string format, IFormatProvider formatProvider)
{
return TimeSpanFormat.Format(this, format, formatProvider);
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeZone.cs b/src/System.Private.CoreLib/shared/System/TimeZone.cs
index d4059babf..010db8090 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZone.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZone.cs
@@ -32,15 +32,15 @@ namespace System
private static volatile TimeZone currentTimeZone = null;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
@@ -87,12 +87,12 @@ namespace System
}
}
- public abstract String StandardName
+ public abstract string StandardName
{
get;
}
- public abstract String DaylightName
+ public abstract string DaylightName
{
get;
}
@@ -129,8 +129,8 @@ namespace System
{
return time;
}
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = ((CurrentSystemTimeZone)(TimeZone.CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ bool isAmbiguousLocalDst = false;
+ long offset = ((CurrentSystemTimeZone)(TimeZone.CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
return new DateTime(time.Ticks + offset, DateTimeKind.Local, isAmbiguousLocalDst);
}
@@ -247,7 +247,7 @@ namespace System
ambiguousEnd = startTime - daylightTimes.Delta;
}
- Boolean isDst = false;
+ bool isDst = false;
if (startTime > endTime)
{
// In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs
index 0e949a30e..aceb7b90f 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs
@@ -11,6 +11,8 @@ namespace System
[Serializable]
public sealed class AdjustmentRule : IEquatable<AdjustmentRule>, ISerializable, IDeserializationCallback
{
+ private static readonly TimeSpan DaylightDeltaAdjustment = TimeSpan.FromHours(24.0);
+ private static readonly TimeSpan MaxDaylightDelta = TimeSpan.FromHours(12.0);
private readonly DateTime _dateStart;
private readonly DateTime _dateEnd;
private readonly TimeSpan _daylightDelta;
@@ -39,8 +41,8 @@ namespace System
internal bool HasDaylightSaving =>
DaylightDelta != TimeSpan.Zero ||
- (DaylightTransitionStart != default(TransitionTime) && DaylightTransitionStart.TimeOfDay != DateTime.MinValue) ||
- (DaylightTransitionEnd != default(TransitionTime) && DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1));
+ (DaylightTransitionStart != default && DaylightTransitionStart.TimeOfDay != DateTime.MinValue) ||
+ (DaylightTransitionEnd != default && DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1));
public bool Equals(AdjustmentRule other) =>
other != null &&
@@ -100,6 +102,7 @@ namespace System
TimeSpan baseUtcOffsetDelta,
bool noDaylightTransitions)
{
+ AdjustDaylightDeltaToExpectedRange(ref daylightDelta, ref baseUtcOffsetDelta);
return new AdjustmentRule(
dateStart,
dateEnd,
@@ -186,6 +189,26 @@ namespace System
}
}
+ /// <summary>
+ /// Ensures the daylight delta is within [-12, 12] hours
+ /// </summary>>
+ private static void AdjustDaylightDeltaToExpectedRange(ref TimeSpan daylightDelta, ref TimeSpan baseUtcOffsetDelta)
+ {
+ if (daylightDelta > MaxDaylightDelta)
+ {
+ daylightDelta -= DaylightDeltaAdjustment;
+ baseUtcOffsetDelta += DaylightDeltaAdjustment;
+ }
+ else if (daylightDelta < -MaxDaylightDelta)
+ {
+ daylightDelta += DaylightDeltaAdjustment;
+ baseUtcOffsetDelta -= DaylightDeltaAdjustment;
+ }
+
+ System.Diagnostics.Debug.Assert(daylightDelta <= MaxDaylightDelta && daylightDelta >= -MaxDaylightDelta,
+ "DaylightDelta should not ever be more than 24h");
+ }
+
void IDeserializationCallback.OnDeserialization(object sender)
{
// OnDeserialization is called after each instance of this class is deserialized.
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs
index 410eaf3ff..5645c2a38 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs
@@ -384,8 +384,8 @@ namespace System
string symlinkPath = Interop.Sys.ReadLink(tzFilePath);
if (symlinkPath != null)
{
- // Use Path.Combine to resolve links that contain a relative path (e.g. /etc/localtime).
- symlinkPath = Path.Combine(tzFilePath, symlinkPath);
+ // symlinkPath can be relative path, use Path to get the full absolute path.
+ symlinkPath = Path.GetFullPath(symlinkPath, Path.GetDirectoryName(tzFilePath));
string timeZoneDirectory = GetTimeZoneDirectory();
if (symlinkPath.StartsWith(timeZoneDirectory, StringComparison.Ordinal))
@@ -398,7 +398,7 @@ namespace System
}
/// <summary>
- /// Enumerate files
+ /// Enumerate files
/// </summary>
private static IEnumerable<string> EnumerateFilesRecursively(string path)
{
@@ -595,6 +595,7 @@ namespace System
}
catch (ArgumentException) { }
catch (InvalidTimeZoneException) { }
+
try
{
return new TimeZoneInfo(rawData, id, dstDisabled: true); // create a TimeZoneInfo instance from the TZif data w/o DST support
@@ -602,7 +603,6 @@ namespace System
catch (ArgumentException) { }
catch (InvalidTimeZoneException) { }
}
-
return null;
}
@@ -866,7 +866,7 @@ namespace System
index++;
}
- if (index == 0)
+ if (rulesList.Count == 0 && index < dts.Length)
{
TZifType transitionType = TZif_GetEarlyDateTransitionType(transitionTypes);
DateTime endTransitionDate = dts[index];
@@ -883,6 +883,12 @@ namespace System
default(TransitionTime),
baseUtcDelta,
noDaylightTransitions: true);
+
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
else if (index < dts.Length)
@@ -920,6 +926,12 @@ namespace System
default(TransitionTime),
baseUtcDelta,
noDaylightTransitions: true);
+
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
else
@@ -932,8 +944,14 @@ namespace System
if (!string.IsNullOrEmpty(futureTransitionsPosixFormat))
{
AdjustmentRule r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset);
+
if (r != null)
{
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
}
@@ -954,6 +972,12 @@ namespace System
default(TransitionTime),
baseUtcDelta,
noDaylightTransitions: true);
+
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
}
@@ -1012,17 +1036,15 @@ namespace System
/// </remarks>
private static AdjustmentRule TZif_CreateAdjustmentRuleForPosixFormat(string posixFormat, DateTime startTransitionDate, TimeSpan timeZoneBaseUtcOffset)
{
- string standardName;
- string standardOffset;
- string daylightSavingsName;
- string daylightSavingsOffset;
- string start;
- string startTime;
- string end;
- string endTime;
-
- if (TZif_ParsePosixFormat(posixFormat, out standardName, out standardOffset, out daylightSavingsName,
- out daylightSavingsOffset, out start, out startTime, out end, out endTime))
+ if (TZif_ParsePosixFormat(posixFormat,
+ out ReadOnlySpan<char> standardName,
+ out ReadOnlySpan<char> standardOffset,
+ out ReadOnlySpan<char> daylightSavingsName,
+ out ReadOnlySpan<char> daylightSavingsOffset,
+ out ReadOnlySpan<char> start,
+ out ReadOnlySpan<char> startTime,
+ out ReadOnlySpan<char> end,
+ out ReadOnlySpan<char> endTime))
{
// a valid posixFormat has at least standardName and standardOffset
@@ -1033,7 +1055,7 @@ namespace System
baseOffset = TZif_CalculateTransitionOffsetFromBase(baseOffset, timeZoneBaseUtcOffset);
// having a daylightSavingsName means there is a DST rule
- if (!string.IsNullOrEmpty(daylightSavingsName))
+ if (!daylightSavingsName.IsEmpty)
{
TimeSpan? parsedDaylightSavings = TZif_ParseOffsetString(daylightSavingsOffset);
TimeSpan daylightSavingsTimeSpan;
@@ -1079,16 +1101,16 @@ namespace System
return null;
}
- private static TimeSpan? TZif_ParseOffsetString(string offset)
+ private static TimeSpan? TZif_ParseOffsetString(ReadOnlySpan<char> offset)
{
TimeSpan? result = null;
- if (!string.IsNullOrEmpty(offset))
+ if (offset.Length > 0)
{
bool negative = offset[0] == '-';
if (negative || offset[0] == '+')
{
- offset = offset.Substring(1);
+ offset = offset.Slice(1);
}
// Try parsing just hours first.
@@ -1117,9 +1139,40 @@ namespace System
return result;
}
- private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(string date, string time)
+ private static DateTime ParseTimeOfDay(ReadOnlySpan<char> time)
+ {
+ DateTime timeOfDay;
+ TimeSpan? timeOffset = TZif_ParseOffsetString(time);
+ if (timeOffset.HasValue)
+ {
+ // This logic isn't correct and can't be corrected until https://github.com/dotnet/corefx/issues/2618 is fixed.
+ // Some time zones use time values like, "26", "144", or "-2".
+ // This allows the week to sometimes be week 4 and sometimes week 5 in the month.
+ // For now, strip off any 'days' in the offset, and just get the time of day correct
+ timeOffset = new TimeSpan(timeOffset.Value.Hours, timeOffset.Value.Minutes, timeOffset.Value.Seconds);
+ if (timeOffset.Value < TimeSpan.Zero)
+ {
+ timeOfDay = new DateTime(1, 1, 2, 0, 0, 0);
+ }
+ else
+ {
+ timeOfDay = new DateTime(1, 1, 1, 0, 0, 0);
+ }
+
+ timeOfDay += timeOffset.Value;
+ }
+ else
+ {
+ // default to 2AM.
+ timeOfDay = new DateTime(1, 1, 1, 2, 0, 0);
+ }
+
+ return timeOfDay;
+ }
+
+ private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(ReadOnlySpan<char> date, ReadOnlySpan<char> time)
{
- if (string.IsNullOrEmpty(date))
+ if (date.IsEmpty)
{
return default(TransitionTime);
}
@@ -1135,51 +1188,93 @@ namespace System
DayOfWeek day;
if (!TZif_ParseMDateRule(date, out month, out week, out day))
{
- throw new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_UnparseablePosixMDateString, date));
+ throw new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_UnparseablePosixMDateString, date.ToString()));
}
- DateTime timeOfDay;
- TimeSpan? timeOffset = TZif_ParseOffsetString(time);
- if (timeOffset.HasValue)
- {
- // This logic isn't correct and can't be corrected until https://github.com/dotnet/corefx/issues/2618 is fixed.
- // Some time zones use time values like, "26", "144", or "-2".
- // This allows the week to sometimes be week 4 and sometimes week 5 in the month.
- // For now, strip off any 'days' in the offset, and just get the time of day correct
- timeOffset = new TimeSpan(timeOffset.Value.Hours, timeOffset.Value.Minutes, timeOffset.Value.Seconds);
- if (timeOffset.Value < TimeSpan.Zero)
- {
- timeOfDay = new DateTime(1, 1, 2, 0, 0, 0);
- }
- else
- {
- timeOfDay = new DateTime(1, 1, 1, 0, 0, 0);
- }
-
- timeOfDay += timeOffset.Value;
- }
- else
+ return TransitionTime.CreateFloatingDateRule(ParseTimeOfDay(time), month, week, day);
+ }
+ else
+ {
+ if (date[0] != 'J')
{
- // default to 2AM.
- timeOfDay = new DateTime(1, 1, 1, 2, 0, 0);
+ // should be n Julian day format which we don't support.
+ //
+ // This specifies the Julian day, with n between 0 and 365. February 29 is counted in leap years.
+ //
+ // n would be a relative number from the begining of the year. which should handle if the
+ // the year is a leap year or not.
+ //
+ // In leap year, n would be counted as:
+ //
+ // 0 30 31 59 60 90 335 365
+ // |-------Jan--------|-------Feb--------|-------Mar--------|....|-------Dec--------|
+ //
+ // while in non leap year we'll have
+ //
+ // 0 30 31 58 59 89 334 364
+ // |-------Jan--------|-------Feb--------|-------Mar--------|....|-------Dec--------|
+ //
+ //
+ // For example if n is specified as 60, this means in leap year the rule will start at Mar 1,
+ // while in non leap year the rule will start at Mar 2.
+ //
+ // If we need to support n format, we'll have to have a floating adjustment rule support this case.
+
+ throw new InvalidTimeZoneException(SR.InvalidTimeZone_NJulianDayNotSupported);
}
- return TransitionTime.CreateFloatingDateRule(timeOfDay, month, week, day);
+ // Julian day
+ TZif_ParseJulianDay(date, out int month, out int day);
+ return TransitionTime.CreateFixedDateRule(ParseTimeOfDay(time), month, day);
}
- else
+ }
+
+ /// <summary>
+ /// Parses a string like Jn or n into month and day values.
+ /// </summary>
+ /// <returns>
+ /// true if the parsing succeeded; otherwise, false.
+ /// </returns>
+ private static void TZif_ParseJulianDay(ReadOnlySpan<char> date, out int month, out int day)
+ {
+ // Jn
+ // This specifies the Julian day, with n between 1 and 365.February 29 is never counted, even in leap years.
+ Debug.Assert(!date.IsEmpty);
+ Debug.Assert(date[0] == 'J');
+ month = day = 0;
+
+ int index = 1;
+
+ if (index >= date.Length || ((uint)(date[index] - '0') > '9'-'0'))
+ {
+ throw new InvalidTimeZoneException(SR.InvalidTimeZone_InvalidJulianDay);
+ }
+
+ int julianDay = 0;
+
+ do
{
- // Jn
- // This specifies the Julian day, with n between 1 and 365.February 29 is never counted, even in leap years.
+ julianDay = julianDay * 10 + (int) (date[index] - '0');
+ index++;
+ } while (index < date.Length && ((uint)(date[index] - '0') <= '9'-'0'));
- // n
- // This specifies the Julian day, with n between 0 and 365.February 29 is counted in leap years.
+ int[] days = GregorianCalendarHelper.DaysToMonth365;
- // These two rules cannot be expressed with the current AdjustmentRules
- // One of them *could* be supported if we relaxed the TransitionTime validation rules, and allowed
- // "IsFixedDateRule = true, Month = 0, Day = n" to mean the nth day of the year, picking one of the rules above
+ if (julianDay == 0 || julianDay > days[days.Length - 1])
+ {
+ throw new InvalidTimeZoneException(SR.InvalidTimeZone_InvalidJulianDay);
+ }
- throw new InvalidTimeZoneException(SR.InvalidTimeZone_JulianDayNotSupported);
+ int i = 1;
+ while (i < days.Length && julianDay > days[i])
+ {
+ i++;
}
+
+ Debug.Assert(i > 0 && i < days.Length);
+
+ month = i;
+ day = julianDay - days[i - 1];
}
/// <summary>
@@ -1188,19 +1283,20 @@ namespace System
/// <returns>
/// true if the parsing succeeded; otherwise, false.
/// </returns>
- private static bool TZif_ParseMDateRule(string dateRule, out int month, out int week, out DayOfWeek dayOfWeek)
+ private static bool TZif_ParseMDateRule(ReadOnlySpan<char> dateRule, out int month, out int week, out DayOfWeek dayOfWeek)
{
if (dateRule[0] == 'M')
{
- int firstDotIndex = dateRule.IndexOf('.');
- if (firstDotIndex > 0)
+ int monthWeekDotIndex = dateRule.IndexOf('.');
+ if (monthWeekDotIndex > 0)
{
- int secondDotIndex = dateRule.IndexOf('.', firstDotIndex + 1);
- if (secondDotIndex > 0)
+ ReadOnlySpan<char> weekDaySpan = dateRule.Slice(monthWeekDotIndex + 1);
+ int weekDayDotIndex = weekDaySpan.IndexOf('.');
+ if (weekDayDotIndex > 0)
{
- if (int.TryParse(dateRule.AsSpan().Slice(1, firstDotIndex - 1), out month) &&
- int.TryParse(dateRule.AsSpan().Slice(firstDotIndex + 1, secondDotIndex - firstDotIndex - 1), out week) &&
- int.TryParse(dateRule.AsSpan().Slice(secondDotIndex + 1), out int day))
+ if (int.TryParse(dateRule.Slice(1, monthWeekDotIndex - 1), out month) &&
+ int.TryParse(weekDaySpan.Slice(0, weekDayDotIndex), out week) &&
+ int.TryParse(weekDaySpan.Slice(weekDayDotIndex + 1), out int day))
{
dayOfWeek = (DayOfWeek)day;
return true;
@@ -1216,15 +1312,15 @@ namespace System
}
private static bool TZif_ParsePosixFormat(
- string posixFormat,
- out string standardName,
- out string standardOffset,
- out string daylightSavingsName,
- out string daylightSavingsOffset,
- out string start,
- out string startTime,
- out string end,
- out string endTime)
+ ReadOnlySpan<char> posixFormat,
+ out ReadOnlySpan<char> standardName,
+ out ReadOnlySpan<char> standardOffset,
+ out ReadOnlySpan<char> daylightSavingsName,
+ out ReadOnlySpan<char> daylightSavingsOffset,
+ out ReadOnlySpan<char> start,
+ out ReadOnlySpan<char> startTime,
+ out ReadOnlySpan<char> end,
+ out ReadOnlySpan<char> endTime)
{
standardName = null;
standardOffset = null;
@@ -1240,7 +1336,7 @@ namespace System
standardOffset = TZif_ParsePosixOffset(posixFormat, ref index);
daylightSavingsName = TZif_ParsePosixName(posixFormat, ref index);
- if (!string.IsNullOrEmpty(daylightSavingsName))
+ if (!daylightSavingsName.IsEmpty)
{
daylightSavingsOffset = TZif_ParsePosixOffset(posixFormat, ref index);
@@ -1257,10 +1353,10 @@ namespace System
}
}
- return !string.IsNullOrEmpty(standardName) && !string.IsNullOrEmpty(standardOffset);
+ return !standardName.IsEmpty && !standardOffset.IsEmpty;
}
- private static string TZif_ParsePosixName(string posixFormat, ref int index)
+ private static ReadOnlySpan<char> TZif_ParsePosixName(ReadOnlySpan<char> posixFormat, ref int index)
{
bool isBracketEnclosed = index < posixFormat.Length && posixFormat[index] == '<';
if (isBracketEnclosed)
@@ -1268,7 +1364,7 @@ namespace System
// move past the opening bracket
index++;
- string result = TZif_ParsePosixString(posixFormat, ref index, c => c == '>');
+ ReadOnlySpan<char> result = TZif_ParsePosixString(posixFormat, ref index, c => c == '>');
// move past the closing bracket
if (index < posixFormat.Length && posixFormat[index] == '>')
@@ -1287,10 +1383,10 @@ namespace System
}
}
- private static string TZif_ParsePosixOffset(string posixFormat, ref int index) =>
+ private static ReadOnlySpan<char> TZif_ParsePosixOffset(ReadOnlySpan<char> posixFormat, ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => !char.IsDigit(c) && c != '+' && c != '-' && c != ':');
- private static void TZif_ParsePosixDateTime(string posixFormat, ref int index, out string date, out string time)
+ private static void TZif_ParsePosixDateTime(ReadOnlySpan<char> posixFormat, ref int index, out ReadOnlySpan<char> date, out ReadOnlySpan<char> time)
{
time = null;
@@ -1302,13 +1398,13 @@ namespace System
}
}
- private static string TZif_ParsePosixDate(string posixFormat, ref int index) =>
+ private static ReadOnlySpan<char> TZif_ParsePosixDate(ReadOnlySpan<char> posixFormat, ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => c == '/' || c == ',');
- private static string TZif_ParsePosixTime(string posixFormat, ref int index) =>
+ private static ReadOnlySpan<char> TZif_ParsePosixTime(ReadOnlySpan<char> posixFormat, ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => c == ',');
- private static string TZif_ParsePosixString(string posixFormat, ref int index, Func<char, bool> breakCondition)
+ private static ReadOnlySpan<char> TZif_ParsePosixString(ReadOnlySpan<char> posixFormat, ref int index, Func<char, bool> breakCondition)
{
int startIndex = index;
for (; index < posixFormat.Length; index++)
@@ -1320,7 +1416,7 @@ namespace System
}
}
- return posixFormat.Substring(startIndex, index - startIndex);
+ return posixFormat.Slice(startIndex, index - startIndex);
}
// Returns the Substring from zoneAbbreviations starting at index and ending at '\0'
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs
index 5950c9565..443b8d45d 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs
@@ -422,7 +422,7 @@ namespace System
if (!supportsDst)
{
- transitionTime = default(TransitionTime);
+ transitionTime = default;
return false;
}
@@ -676,7 +676,7 @@ namespace System
return true;
}
- private unsafe static bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi)
+ private static unsafe bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi)
{
byte[] regValue = key.GetValue(name, null, RegistryValueOptions.None) as byte[];
if (regValue == null || regValue.Length != sizeof(REG_TZI_FORMAT))
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs
index 6e27376b6..e95321df2 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs
@@ -1918,12 +1918,6 @@ namespace System
}
/// <summary>
- /// Helper function that validates the TimeSpan is within +/- 14.0 hours
- /// </summary>
- internal static bool UtcOffsetOutOfRange(TimeSpan offset) =>
- offset.TotalHours < -14.0 || offset.TotalHours > 14.0;
-
- /// <summary>
/// Helper function that performs all of the validation checks for the
/// factory methods and deserialization callback.
/// </summary>
@@ -1972,11 +1966,7 @@ namespace System
throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesNoNulls);
}
- // FUTURE: check to see if this rule supports Daylight Saving Time
- // adjustmentRulesSupportDst = adjustmentRulesSupportDst || current.SupportsDaylightSavingTime;
- // FUTURE: test baseUtcOffset + current.StandardDelta
-
- if (UtcOffsetOutOfRange(baseUtcOffset + current.DaylightDelta))
+ if (!IsValidAdjustmentRuleOffest(baseUtcOffset, current))
{
throw new InvalidTimeZoneException(SR.ArgumentOutOfRange_UtcOffsetAndDaylightDelta);
}
@@ -1989,5 +1979,82 @@ namespace System
}
}
}
+
+ private static readonly TimeSpan MaxOffset = TimeSpan.FromHours(14.0);
+ private static readonly TimeSpan MinOffset = -MaxOffset;
+
+ /// <summary>
+ /// Helper function that validates the TimeSpan is within +/- 14.0 hours
+ /// </summary>
+ internal static bool UtcOffsetOutOfRange(TimeSpan offset) =>
+ offset < MinOffset || offset > MaxOffset;
+
+ private static TimeSpan GetUtcOffset(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule)
+ {
+ return baseUtcOffset
+ + adjustmentRule.BaseUtcOffsetDelta
+ + (adjustmentRule.HasDaylightSaving ? adjustmentRule.DaylightDelta : TimeSpan.Zero);
+ }
+
+ /// <summary>
+ /// Helper function that performs adjustment rule validation
+ /// </summary>
+ private static bool IsValidAdjustmentRuleOffest(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule)
+ {
+ TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule);
+ return !UtcOffsetOutOfRange(utcOffset);
+ }
+
+ /// <summary>
+ /// Normalize adjustment rule offset so that it is within valid range
+ /// This method should not be called at all but is here in case something changes in the future
+ /// or if really old time zones are present on the OS (no combination is known at the moment)
+ /// </summary>
+ private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, ref AdjustmentRule adjustmentRule)
+ {
+ // Certain time zones such as:
+ // Time Zone start date end date offset
+ // -----------------------------------------------------
+ // America/Yakutat 0001-01-01 1867-10-18 14:41:00
+ // America/Yakutat 1867-10-18 1900-08-20 14:41:00
+ // America/Sitka 0001-01-01 1867-10-18 14:58:00
+ // America/Sitka 1867-10-18 1900-08-20 14:58:00
+ // Asia/Manila 0001-01-01 1844-12-31 -15:56:00
+ // Pacific/Guam 0001-01-01 1845-01-01 -14:21:00
+ // Pacific/Saipan 0001-01-01 1845-01-01 -14:21:00
+ //
+ // have larger offset than currently supported by framework.
+ // If for whatever reason we find that time zone exceeding max
+ // offset of 14h this function will truncate it to the max valid offset.
+ // Updating max offset may cause problems with interacting with SQL server
+ // which uses SQL DATETIMEOFFSET field type which was originally designed to be
+ // bit-for-bit compatible with DateTimeOffset.
+
+ TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule);
+
+ // utc base offset delta increment
+ TimeSpan adjustment = TimeSpan.Zero;
+
+ if (utcOffset > MaxOffset)
+ {
+ adjustment = MaxOffset - utcOffset;
+ }
+ else if (utcOffset < MinOffset)
+ {
+ adjustment = MinOffset - utcOffset;
+ }
+
+ if (adjustment != TimeSpan.Zero)
+ {
+ adjustmentRule = AdjustmentRule.CreateAdjustmentRule(
+ adjustmentRule.DateStart,
+ adjustmentRule.DateEnd,
+ adjustmentRule.DaylightDelta,
+ adjustmentRule.DaylightTransitionStart,
+ adjustmentRule.DaylightTransitionEnd,
+ adjustmentRule.BaseUtcOffsetDelta + adjustment,
+ adjustmentRule.NoDaylightTransitions);
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs b/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs
index f83c6443c..3dc1bb1d4 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs
@@ -14,12 +14,12 @@ namespace System
{
}
- public TimeZoneNotFoundException(String message)
+ public TimeZoneNotFoundException(string message)
: base(message)
{
}
- public TimeZoneNotFoundException(String message, Exception innerException)
+ public TimeZoneNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeoutException.cs b/src/System.Private.CoreLib/shared/System/TimeoutException.cs
index ddaa47747..2480f4bc2 100644
--- a/src/System.Private.CoreLib/shared/System/TimeoutException.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeoutException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_TIMEOUT;
}
- public TimeoutException(String message)
+ public TimeoutException(string message)
: base(message)
{
HResult = HResults.COR_E_TIMEOUT;
}
- public TimeoutException(String message, Exception innerException)
+ public TimeoutException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_TIMEOUT;
diff --git a/src/System.Private.CoreLib/shared/System/Tuple.cs b/src/System.Private.CoreLib/shared/System/Tuple.cs
index 141ae08dc..8529e01f9 100644
--- a/src/System.Private.CoreLib/shared/System/Tuple.cs
+++ b/src/System.Private.CoreLib/shared/System/Tuple.cs
@@ -117,12 +117,12 @@ namespace System
m_Item1 = item1;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default);
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -136,12 +136,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -157,15 +157,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return comparer.GetHashCode(m_Item1);
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -222,12 +222,12 @@ namespace System
m_Item2 = item2;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -241,12 +241,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -268,15 +268,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -342,12 +342,12 @@ namespace System
m_Item3 = item3;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -361,12 +361,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -392,15 +392,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -473,12 +473,12 @@ namespace System
m_Item4 = item4;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -492,12 +492,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -527,15 +527,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -615,12 +615,12 @@ namespace System
m_Item5 = item5;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -634,12 +634,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -673,15 +673,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -768,12 +768,12 @@ namespace System
m_Item6 = item6;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -787,12 +787,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -830,15 +830,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -932,12 +932,12 @@ namespace System
m_Item7 = item7;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -951,12 +951,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -998,15 +998,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -1112,12 +1112,12 @@ namespace System
m_Rest = rest;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -1131,12 +1131,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7) && comparer.Equals(m_Rest, objTuple.m_Rest);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -1182,10 +1182,10 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
// We want to have a limited hash in this case. We'll use the last 8 elements of the tuple
ITupleInternal t = (ITupleInternal)m_Rest;
@@ -1214,7 +1214,7 @@ namespace System
return -1;
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
diff --git a/src/System.Private.CoreLib/shared/System/Type.Helpers.cs b/src/System.Private.CoreLib/shared/System/Type.Helpers.cs
index db8df231e..3de7d827e 100644
--- a/src/System.Private.CoreLib/shared/System/Type.Helpers.cs
+++ b/src/System.Private.CoreLib/shared/System/Type.Helpers.cs
@@ -473,54 +473,31 @@ namespace System
// This method will filter based upon the name. A partial wildcard
// at the end of the string is supported.
// filterCriteria -- This is the string name
- private static bool FilterNameImpl(MemberInfo m, object filterCriteria)
+ private static bool FilterNameImpl(MemberInfo m, object filterCriteria, StringComparison comparison)
{
// Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
+ if (!(filterCriteria is string filterCriteriaString))
+ {
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
+ }
- // At the moment this fails if its done on a single line....
- string str = ((string)filterCriteria);
- str = str.Trim();
+ ReadOnlySpan<char> str = filterCriteriaString.AsSpan().Trim();
+ ReadOnlySpan<char> name = m.Name;
- string name = m.Name;
// Get the nested class name only, as opposed to the mangled one
if (m.MemberType == MemberTypes.NestedType)
- name = name.Substring(name.LastIndexOf('+') + 1);
- // Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- return (name.StartsWith(str, StringComparison.Ordinal));
+ name = name.Slice(name.LastIndexOf('+') + 1);
}
- return (name.Equals(str));
- }
-
- // FilterIgnoreCase
- // This delegate will do a name search but does it with the
- // ignore case specified.
- private static bool FilterNameIgnoreCaseImpl(MemberInfo m, object filterCriteria)
- {
- // Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
- throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
- str = str.Trim();
-
- string name = m.Name;
- // Get the nested class name only, as opposed to the mangled one
- if (m.MemberType == MemberTypes.NestedType)
- name = name.Substring(name.LastIndexOf('+') + 1);
// Check to see if this is a prefix or exact match requirement
if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0);
+ str = str.Slice(0, str.Length - 1);
+ return name.StartsWith(str, comparison);
}
- return (string.Compare(str, name, StringComparison.OrdinalIgnoreCase) == 0);
+ return name.Equals(str, comparison);
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Type.cs b/src/System.Private.CoreLib/shared/System/Type.cs
index a0d219ddd..c78d98833 100644
--- a/src/System.Private.CoreLib/shared/System/Type.cs
+++ b/src/System.Private.CoreLib/shared/System/Type.cs
@@ -346,10 +346,12 @@ namespace System
public virtual Type MakeGenericType(params Type[] typeArguments) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
public virtual Type MakePointerType() { throw new NotSupportedException(); }
+ public static Type MakeGenericSignatureType(Type genericTypeDefinition, params Type[] typeArguments) => new SignatureConstructedGenericType(genericTypeDefinition, typeArguments);
+
public static Type MakeGenericMethodParameter(int position)
{
if (position < 0)
- throw new ArgumentException(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(position));
+ throw new ArgumentException(SR.ArgumentOutOfRange_NeedNonNegNum, nameof(position));
return new SignatureGenericMethodParameterType(position);
}
@@ -387,8 +389,8 @@ namespace System
public static readonly object Missing = System.Reflection.Missing.Value;
public static readonly MemberFilter FilterAttribute = FilterAttributeImpl;
- public static readonly MemberFilter FilterName = FilterNameImpl;
- public static readonly MemberFilter FilterNameIgnoreCase = FilterNameIgnoreCaseImpl;
+ public static readonly MemberFilter FilterName = (m, c) => FilterNameImpl(m, c, StringComparison.Ordinal);
+ public static readonly MemberFilter FilterNameIgnoreCase = (m, c) => FilterNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
}
diff --git a/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs b/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs
index 4bf290621..2ef822ab2 100644
--- a/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs
+++ b/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs
@@ -23,7 +23,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed class TypeInitializationException : SystemException
{
- private String _typeName;
+ private string _typeName;
// This exception is not creatable without specifying the
// inner exception.
@@ -34,19 +34,19 @@ namespace System
}
- public TypeInitializationException(String fullTypeName, Exception innerException)
+ public TypeInitializationException(string fullTypeName, Exception innerException)
: this(fullTypeName, SR.Format(SR.TypeInitialization_Type, fullTypeName), innerException)
{
}
// This is called from within the runtime. I believe this is necessary
// for Interop only, though it's not particularly useful.
- internal TypeInitializationException(String message) : base(message)
+ internal TypeInitializationException(string message) : base(message)
{
HResult = HResults.COR_E_TYPEINITIALIZATION;
}
- internal TypeInitializationException(String fullTypeName, String message, Exception innerException)
+ internal TypeInitializationException(string fullTypeName, string message, Exception innerException)
: base(message, innerException)
{
_typeName = fullTypeName;
@@ -65,13 +65,13 @@ namespace System
info.AddValue("TypeName", TypeName, typeof(string));
}
- public String TypeName
+ public string TypeName
{
get
{
if (_typeName == null)
{
- return String.Empty;
+ return string.Empty;
}
return _typeName;
}
diff --git a/src/System.Private.CoreLib/shared/System/UInt16.cs b/src/System.Private.CoreLib/shared/System/UInt16.cs
index 3047d1819..f9ef1f6a6 100644
--- a/src/System.Private.CoreLib/shared/System/UInt16.cs
+++ b/src/System.Private.CoreLib/shared/System/UInt16.cs
@@ -13,9 +13,9 @@ namespace System
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UInt16 : IComparable, IConvertible, IFormattable, IComparable<UInt16>, IEquatable<UInt16>, ISpanFormattable
+ public readonly struct UInt16 : IComparable, IConvertible, IFormattable, IComparable<ushort>, IEquatable<ushort>, ISpanFormattable
{
- private ushort m_value; // Do not rename (binary serialization)
+ private readonly ushort m_value; // Do not rename (binary serialization)
public const ushort MaxValue = (ushort)0xFFFF;
public const ushort MinValue = 0;
@@ -27,35 +27,35 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type UInt16, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is UInt16)
+ if (value is ushort)
{
- return ((int)m_value - (int)(((UInt16)value).m_value));
+ return ((int)m_value - (int)(((ushort)value).m_value));
}
throw new ArgumentException(SR.Arg_MustBeUInt16);
}
- public int CompareTo(UInt16 value)
+ public int CompareTo(ushort value)
{
return ((int)m_value - (int)value);
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is UInt16))
+ if (!(obj is ushort))
{
return false;
}
- return m_value == ((UInt16)obj).m_value;
+ return m_value == ((ushort)obj).m_value;
}
[NonVersionable]
- public bool Equals(UInt16 obj)
+ public bool Equals(ushort obj)
{
return m_value == obj;
}
@@ -67,23 +67,23 @@ namespace System
}
// Converts the current value to a String in base-10 with no extra padding.
- public override String ToString()
+ public override string ToString()
{
return Number.FormatUInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatUInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatUInt32(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatUInt32(m_value, format, provider);
}
@@ -94,14 +94,14 @@ namespace System
}
[CLSCompliant(false)]
- public static ushort Parse(String s)
+ public static ushort Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static ushort Parse(String s, NumberStyles style)
+ public static ushort Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -110,14 +110,14 @@ namespace System
[CLSCompliant(false)]
- public static ushort Parse(String s, IFormatProvider provider)
+ public static ushort Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
[CLSCompliant(false)]
- public static ushort Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static ushort Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -148,7 +148,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, out UInt16 result)
+ public static bool TryParse(string s, out ushort result)
{
if (s == null)
{
@@ -166,7 +166,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt16 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out ushort result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -186,10 +186,10 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out UInt16 result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out ushort result)
{
result = 0;
- UInt32 i;
+ uint i;
if (!Number.TryParseUInt32(s, style, info, out i))
{
return false;
@@ -198,7 +198,7 @@ namespace System
{
return false;
}
- result = (UInt16)i;
+ result = (ushort)i;
return true;
}
@@ -271,7 +271,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -281,7 +281,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt16", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/UInt32.cs b/src/System.Private.CoreLib/shared/System/UInt32.cs
index 1e33dcf17..5ed193e95 100644
--- a/src/System.Private.CoreLib/shared/System/UInt32.cs
+++ b/src/System.Private.CoreLib/shared/System/UInt32.cs
@@ -13,9 +13,9 @@ namespace System
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UInt32 : IComparable, IConvertible, IFormattable, IComparable<UInt32>, IEquatable<UInt32>, ISpanFormattable
+ public readonly struct UInt32 : IComparable, IConvertible, IFormattable, IComparable<uint>, IEquatable<uint>, ISpanFormattable
{
- private uint m_value; // Do not rename (binary serialization)
+ private readonly uint m_value; // Do not rename (binary serialization)
public const uint MaxValue = (uint)0xffffffff;
public const uint MinValue = 0U;
@@ -27,13 +27,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type UInt32, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is UInt32)
+ if (value is uint)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -45,7 +45,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeUInt32);
}
- public int CompareTo(UInt32 value)
+ public int CompareTo(uint value)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -54,17 +54,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is UInt32))
+ if (!(obj is uint))
{
return false;
}
- return m_value == ((UInt32)obj).m_value;
+ return m_value == ((uint)obj).m_value;
}
[NonVersionable]
- public bool Equals(UInt32 obj)
+ public bool Equals(uint obj)
{
return m_value == obj;
}
@@ -76,22 +76,22 @@ namespace System
}
// The base 10 representation of the number with no extra padding.
- public override String ToString()
+ public override string ToString()
{
return Number.FormatUInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatUInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatUInt32(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatUInt32(m_value, format, provider);
}
@@ -102,14 +102,14 @@ namespace System
}
[CLSCompliant(false)]
- public static uint Parse(String s)
+ public static uint Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static uint Parse(String s, NumberStyles style)
+ public static uint Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -118,14 +118,14 @@ namespace System
[CLSCompliant(false)]
- public static uint Parse(String s, IFormatProvider provider)
+ public static uint Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
[CLSCompliant(false)]
- public static uint Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static uint Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -140,7 +140,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, out UInt32 result)
+ public static bool TryParse(string s, out uint result)
{
if (s == null)
{
@@ -158,7 +158,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt32 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out uint result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -247,7 +247,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -257,7 +257,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt32", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/UInt64.cs b/src/System.Private.CoreLib/shared/System/UInt64.cs
index d30fbe1e4..6abd76da2 100644
--- a/src/System.Private.CoreLib/shared/System/UInt64.cs
+++ b/src/System.Private.CoreLib/shared/System/UInt64.cs
@@ -13,9 +13,9 @@ namespace System
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UInt64 : IComparable, IConvertible, IFormattable, IComparable<UInt64>, IEquatable<UInt64>, ISpanFormattable
+ public readonly struct UInt64 : IComparable, IConvertible, IFormattable, IComparable<ulong>, IEquatable<ulong>, ISpanFormattable
{
- private ulong m_value; // Do not rename (binary serialization)
+ private readonly ulong m_value; // Do not rename (binary serialization)
public const ulong MaxValue = (ulong)0xffffffffffffffffL;
public const ulong MinValue = 0x0;
@@ -26,13 +26,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type UInt64, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is UInt64)
+ if (value is ulong)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -44,7 +44,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeUInt64);
}
- public int CompareTo(UInt64 value)
+ public int CompareTo(ulong value)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -53,17 +53,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is UInt64))
+ if (!(obj is ulong))
{
return false;
}
- return m_value == ((UInt64)obj).m_value;
+ return m_value == ((ulong)obj).m_value;
}
[NonVersionable]
- public bool Equals(UInt64 obj)
+ public bool Equals(ulong obj)
{
return m_value == obj;
}
@@ -74,22 +74,22 @@ namespace System
return ((int)m_value) ^ (int)(m_value >> 32);
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatUInt64(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatUInt64(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatUInt64(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatUInt64(m_value, format, provider);
}
@@ -100,14 +100,14 @@ namespace System
}
[CLSCompliant(false)]
- public static ulong Parse(String s)
+ public static ulong Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static ulong Parse(String s, NumberStyles style)
+ public static ulong Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -122,7 +122,7 @@ namespace System
}
[CLSCompliant(false)]
- public static ulong Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static ulong Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -137,7 +137,7 @@ namespace System
}
[CLSCompliant(false)]
- public static Boolean TryParse(String s, out UInt64 result)
+ public static bool TryParse(string s, out ulong result)
{
if (s == null)
{
@@ -155,7 +155,7 @@ namespace System
}
[CLSCompliant(false)]
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt64 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out ulong result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -244,7 +244,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -254,7 +254,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt64", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/UIntPtr.cs b/src/System.Private.CoreLib/shared/System/UIntPtr.cs
index 23750e95f..c57dd86a7 100644
--- a/src/System.Private.CoreLib/shared/System/UIntPtr.cs
+++ b/src/System.Private.CoreLib/shared/System/UIntPtr.cs
@@ -18,9 +18,9 @@ namespace System
[Serializable]
[CLSCompliant(false)]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UIntPtr : IEquatable<UIntPtr>, ISerializable
+ public readonly struct UIntPtr : IEquatable<UIntPtr>, ISerializable
{
- unsafe private void* _value; // Do not rename (binary serialization)
+ private readonly unsafe void* _value; // Do not rename (binary serialization)
[Intrinsic]
public static readonly UIntPtr Zero;
@@ -68,7 +68,7 @@ namespace System
info.AddValue("value", ToUInt64());
}
- public unsafe override bool Equals(Object obj)
+ public unsafe override bool Equals(object obj)
{
if (obj is UIntPtr)
{
@@ -77,9 +77,9 @@ namespace System
return false;
}
- unsafe bool IEquatable<UIntPtr>.Equals(UIntPtr value)
+ unsafe bool IEquatable<UIntPtr>.Equals(UIntPtr other)
{
- return _value == value._value;
+ return _value == other._value;
}
public unsafe override int GetHashCode()
@@ -208,6 +208,9 @@ namespace System
[Intrinsic]
[NonVersionable]
+#if PROJECTN
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+#endif
public unsafe void* ToPointer()
{
return _value;
diff --git a/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs b/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs
index a28f6dd73..e384dfeb3 100644
--- a/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs
@@ -29,13 +29,13 @@ namespace System
HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
- public UnauthorizedAccessException(String message)
+ public UnauthorizedAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
- public UnauthorizedAccessException(String message, Exception inner)
+ public UnauthorizedAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs
index 5cde57216..c214afdc7 100644
--- a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs
+++ b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs
@@ -6,16 +6,16 @@ namespace System
{
public class UnhandledExceptionEventArgs : EventArgs
{
- private Object _exception;
+ private object _exception;
private bool _isTerminating;
- public UnhandledExceptionEventArgs(Object exception, bool isTerminating)
+ public UnhandledExceptionEventArgs(object exception, bool isTerminating)
{
_exception = exception;
_isTerminating = isTerminating;
}
- public Object ExceptionObject
+ public object ExceptionObject
{
get { return _exception; }
}
diff --git a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs
index 14e31c7bb..58f1eb514 100644
--- a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs
+++ b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs
@@ -4,5 +4,5 @@
namespace System
{
- public delegate void UnhandledExceptionEventHandler(Object sender, UnhandledExceptionEventArgs e);
+ public delegate void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e);
}
diff --git a/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs b/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs
index 2f3035670..53323c32b 100644
--- a/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs
+++ b/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs
@@ -11,12 +11,8 @@ namespace System
/// This only exists for compatibility with .NET Framework.
/// </summary>
[Serializable]
-#if CORERT
- public
-#else
- internal
-#endif
- sealed class UnitySerializationHolder : ISerializable, IObjectReference
+ // Needs to be public to support binary serialization compatibility
+ public sealed class UnitySerializationHolder : ISerializable, IObjectReference
{
internal const int NullUnity = 0x0002;
private readonly int _unityType;
diff --git a/src/System.Private.CoreLib/shared/System/ValueTuple.cs b/src/System.Private.CoreLib/shared/System/ValueTuple.cs
index e89d83097..b486573ff 100644
--- a/src/System.Private.CoreLib/shared/System/ValueTuple.cs
+++ b/src/System.Private.CoreLib/shared/System/ValueTuple.cs
@@ -638,7 +638,7 @@ namespace System
/// The string returned by this method takes the form <c>(Item1, Item2)</c>,
/// where <c>Item1</c> and <c>Item2</c> represent the values of the <see cref="Item1"/>
/// and <see cref="Item2"/> fields. If either field value is <see langword="null"/>,
- /// it is represented as <see cref="String.Empty"/>.
+ /// it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -846,7 +846,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1073,7 +1073,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1319,7 +1319,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1584,7 +1584,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1868,7 +1868,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -2270,7 +2270,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7, Rest)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
diff --git a/src/System.Private.CoreLib/shared/System/Version.cs b/src/System.Private.CoreLib/shared/System/Version.cs
index 9e4cefcd6..444ee4885 100644
--- a/src/System.Private.CoreLib/shared/System/Version.cs
+++ b/src/System.Private.CoreLib/shared/System/Version.cs
@@ -73,7 +73,7 @@ namespace System
_Minor = minor;
}
- public Version(String version)
+ public Version(string version)
{
Version v = Version.Parse(version);
_Major = v.Major;
@@ -134,7 +134,7 @@ namespace System
get { return (short)(_Revision & 0xFFFF); }
}
- public int CompareTo(Object version)
+ public int CompareTo(object version)
{
if (version == null)
{
@@ -154,7 +154,7 @@ namespace System
{
return
object.ReferenceEquals(value, this) ? 0 :
- object.ReferenceEquals(value, null) ? 1 :
+ value is null ? 1 :
_Major != value._Major ? (_Major > value._Major ? 1 : -1) :
_Minor != value._Minor ? (_Minor > value._Minor ? 1 : -1) :
_Build != value._Build ? (_Build > value._Build ? 1 : -1) :
@@ -162,7 +162,7 @@ namespace System
0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
return Equals(obj as Version);
}
@@ -170,7 +170,7 @@ namespace System
public bool Equals(Version obj)
{
return object.ReferenceEquals(obj, this) ||
- (!object.ReferenceEquals(obj, null) &&
+ (!(obj is null) &&
_Major == obj._Major &&
_Minor == obj._Minor &&
_Build == obj._Build &&
@@ -333,13 +333,15 @@ namespace System
// Find the ends of the optional minor and build portions.
// We musn't have any separators after build.
int buildEnd = -1;
- int minorEnd = input.IndexOf('.', majorEnd + 1);
+ int minorEnd = input.Slice(majorEnd + 1).IndexOf('.');
if (minorEnd != -1)
{
- buildEnd = input.IndexOf('.', minorEnd + 1);
+ minorEnd += (majorEnd + 1);
+ buildEnd = input.Slice(minorEnd + 1).IndexOf('.');
if (buildEnd != -1)
{
- if (input.IndexOf('.', buildEnd + 1) != -1)
+ buildEnd += (minorEnd + 1);
+ if (input.Slice(buildEnd + 1).Contains('.'))
{
if (throwOnFailure) throw new ArgumentException(SR.Arg_VersionString, nameof(input));
return null;
@@ -347,10 +349,10 @@ namespace System
}
}
- int major, minor, build, revision;
+ int minor, build, revision;
// Parse the major version
- if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out major))
+ if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out int major))
{
return null;
}
@@ -405,9 +407,9 @@ namespace System
public static bool operator ==(Version v1, Version v2)
{
- if (Object.ReferenceEquals(v1, null))
+ if (v1 is null)
{
- return Object.ReferenceEquals(v2, null);
+ return v2 is null;
}
return v1.Equals(v2);
@@ -420,14 +422,14 @@ namespace System
public static bool operator <(Version v1, Version v2)
{
- if ((Object)v1 == null)
+ if ((object)v1 == null)
throw new ArgumentNullException(nameof(v1));
return (v1.CompareTo(v2) < 0);
}
public static bool operator <=(Version v1, Version v2)
{
- if ((Object)v1 == null)
+ if ((object)v1 == null)
throw new ArgumentNullException(nameof(v1));
return (v1.CompareTo(v2) <= 0);
}