Decompiled source of Custom Boombox Music Opus v1.4.0

Concentus.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using Concentus.Celt;
using Concentus.Celt.Structs;
using Concentus.Common;
using Concentus.Common.CPlusPlus;
using Concentus.Enums;
using Concentus.Native;
using Concentus.Silk;
using Concentus.Silk.Enums;
using Concentus.Silk.Structs;
using Concentus.Structs;
using Microsoft.CodeAnalysis;
using Microsoft.Win32.SafeHandles;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("ParityTest, PublicKey=002400000480000094000000060200000024000052534131000400000100010071a2f675c04c87e64b9be6d37f5833c5285fb4ed883780cf6d61e80aee5d77950b2f06dd45bc634f53405f2a2b7b2332f4dfdcb0554ffc97b935e7343e76e733eea44346e56ac1098c12a66de71e324f2f503f9f2e32560910e2082d6943df50db42679a330e52979bd1eefbb59485d2c7420d158f6ab6d41bdf42d2172675e1")]
[assembly: InternalsVisibleTo("TestOpusEncode, PublicKey=002400000480000094000000060200000024000052534131000400000100010071a2f675c04c87e64b9be6d37f5833c5285fb4ed883780cf6d61e80aee5d77950b2f06dd45bc634f53405f2a2b7b2332f4dfdcb0554ffc97b935e7343e76e733eea44346e56ac1098c12a66de71e324f2f503f9f2e32560910e2082d6943df50db42679a330e52979bd1eefbb59485d2c7420d158f6ab6d41bdf42d2172675e1")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Logan Stromberg")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("© Xiph.Org Foundation, Skype Limited, CSIRO, Microsoft Corp.")]
[assembly: AssemblyDescription("This package is a portable C# implementation of the Opus audio compression codec (see https://opus-codec.org/ for more details). This package contains the Opus encoder, decoder, multistream codecs, repacketizer, as well as a port of the libspeexdsp resampler. It does NOT contain code to parse .ogg or .opus container files or to manage RTP packet streams. For better performance depending on your platform, see also the Concentus.Native package.")]
[assembly: AssemblyFileVersion("2.2.2.0")]
[assembly: AssemblyInformationalVersion("2.2.2+6c2328dc19044601e33a9c11628b8d60e1f3011c")]
[assembly: AssemblyProduct("Concentus")]
[assembly: AssemblyTitle("Concentus")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/lostromb/concentus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.2.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
namespace Concentus
{
	public interface IOpusDecoder : IDisposable
	{
		OpusBandwidth Bandwidth { get; }

		uint FinalRange { get; }

		int Gain { get; set; }

		int LastPacketDuration { get; }

		int NumChannels { get; }

		int Pitch { get; }

		int SampleRate { get; }

		int Decode(ReadOnlySpan<byte> in_data, Span<float> out_pcm, int frame_size, bool decode_fec = false);

		int Decode(ReadOnlySpan<byte> in_data, Span<short> out_pcm, int frame_size, bool decode_fec = false);

		void ResetState();

		string GetVersionString();
	}
	public interface IOpusEncoder : IDisposable
	{
		OpusApplication Application { get; set; }

		int Bitrate { get; set; }

		int ForceChannels { get; set; }

		OpusBandwidth MaxBandwidth { get; set; }

		OpusBandwidth Bandwidth { get; set; }

		bool UseDTX { get; set; }

		int Complexity { get; set; }

		bool UseInbandFEC { get; set; }

		int PacketLossPercent { get; set; }

		bool UseVBR { get; set; }

		bool UseConstrainedVBR { get; set; }

		OpusSignal SignalType { get; set; }

		int Lookahead { get; }

		int SampleRate { get; }

		int NumChannels { get; }

		uint FinalRange { get; }

		int LSBDepth { get; set; }

		OpusFramesize ExpertFrameDuration { get; set; }

		OpusMode ForceMode { set; }

		bool PredictionDisabled { get; set; }

		int Encode(ReadOnlySpan<short> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		int Encode(ReadOnlySpan<float> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		void ResetState();

		string GetVersionString();
	}
	public interface IOpusMultiStreamDecoder : IDisposable
	{
		OpusBandwidth Bandwidth { get; }

		uint FinalRange { get; }

		int Gain { get; set; }

		int LastPacketDuration { get; }

		int SampleRate { get; }

		int NumChannels { get; }

		int DecodeMultistream(ReadOnlySpan<byte> data, Span<float> out_pcm, int frame_size, bool decode_fec);

		int DecodeMultistream(ReadOnlySpan<byte> data, Span<short> out_pcm, int frame_size, bool decode_fec);

		void ResetState();

		string GetVersionString();
	}
	public interface IOpusMultiStreamEncoder : IDisposable
	{
		OpusApplication Application { get; set; }

		OpusBandwidth Bandwidth { get; set; }

		int Bitrate { get; set; }

		int Complexity { get; set; }

		int NumChannels { get; }

		OpusFramesize ExpertFrameDuration { get; set; }

		uint FinalRange { get; }

		OpusMode ForceMode { set; }

		int Lookahead { get; }

		int LSBDepth { get; set; }

		OpusBandwidth MaxBandwidth { get; set; }

		int PacketLossPercent { get; set; }

		bool PredictionDisabled { get; set; }

		int SampleRate { get; }

		OpusSignal SignalType { get; set; }

		bool UseConstrainedVBR { get; set; }

		bool UseDTX { get; set; }

		bool UseInbandFEC { get; set; }

		bool UseVBR { get; set; }

		int EncodeMultistream(ReadOnlySpan<float> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		int EncodeMultistream(ReadOnlySpan<short> in_pcm, int frame_size, Span<byte> out_data, int max_data_bytes);

		void ResetState();

		string GetVersionString();
	}
	public interface IResampler : IDisposable
	{
		int InputLatency { get; }

		int InputStride { get; set; }

		int OutputLatencySamples { get; }

		TimeSpan OutputLatency { get; }

		int OutputStride { get; set; }

		int Quality { get; set; }

		void GetRateFraction(out int ratio_num, out int ratio_den);

		void GetRates(out int in_rate, out int out_rate);

		void ResetMem();

		void SkipZeroes();

		void Process(int channel_index, Span<float> input, ref int in_len, Span<float> output, ref int out_len);

		void Process(int channel_index, Span<short> input, ref int in_len, Span<short> output, ref int out_len);

		void ProcessInterleaved(Span<float> input, ref int in_len, Span<float> output, ref int out_len);

		void ProcessInterleaved(Span<short> input, ref int in_len, Span<short> output, ref int out_len);

		void SetRateFraction(int ratio_num, int ratio_den, int in_rate, int out_rate);

		void SetRates(int in_rate, int out_rate);
	}
	public static class OpusCodecFactory
	{
		private static readonly object _mutex = new object();

		private static bool _nativeLibInitialized = false;

		private static bool _isNativeLibAvailable = false;

		private static bool _userAllowNativeLib = true;

		public static bool AttemptToUseNativeLibrary
		{
			get
			{
				return _userAllowNativeLib;
			}
			set
			{
				_userAllowNativeLib = value;
			}
		}

		public static IOpusEncoder CreateEncoder(int sampleRate, int numChannels, OpusApplication application = OpusApplication.OPUS_APPLICATION_AUDIO, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusEncoder.Create(sampleRate, numChannels, application);
			}
			return new OpusEncoder(sampleRate, numChannels, application);
		}

		public static IOpusDecoder CreateDecoder(int sampleRate, int numChannels, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusDecoder.Create(sampleRate, numChannels);
			}
			return new OpusDecoder(sampleRate, numChannels);
		}

		public static IOpusMultiStreamEncoder CreateMultiStreamEncoder(int sampleRate, int numChannels, int mappingFamily, out int streams, out int coupledStreams, byte[] mapping, OpusApplication application, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusMultistreamEncoder.Create(sampleRate, numChannels, mappingFamily, out streams, out coupledStreams, mapping, application);
			}
			return OpusMSEncoder.CreateSurround(sampleRate, numChannels, mappingFamily, out streams, out coupledStreams, mapping, application);
		}

		public static IOpusMultiStreamDecoder CreateMultiStreamDecoder(int sampleRate, int numChannels, int streams, int coupledStreams, byte[] mapping, TextWriter messageLogger = null)
		{
			if (_userAllowNativeLib && NativeLibraryAvailable(messageLogger))
			{
				return NativeOpusMultistreamDecoder.Create(sampleRate, numChannels, streams, coupledStreams, mapping);
			}
			return new OpusMSDecoder(sampleRate, numChannels, streams, coupledStreams, mapping);
		}

		private static bool NativeLibraryAvailable(TextWriter messageLogger)
		{
			lock (_mutex)
			{
				if (!_nativeLibInitialized)
				{
					try
					{
						_isNativeLibAvailable = NativeOpus.Initialize(messageLogger);
						messageLogger?.WriteLine($"Is native opus available? {_isNativeLibAvailable}");
					}
					catch (Exception ex)
					{
						messageLogger?.WriteLine(ex.ToString());
					}
					_nativeLibInitialized = true;
				}
				return _isNativeLibAvailable;
			}
		}
	}
	internal static class Analysis
	{
		private const double M_PI = 3.141592653;

		private const float cA = 0.43157974f;

		private const float cB = 0.678484f;

		private const float cC = 0.08595542f;

		private const float cE = MathF.PI / 2f;

		private const int NB_TONAL_SKIP_BANDS = 9;

		internal static float fast_atan2f(float y, float x)
		{
			if (Inlines.ABS16(x) + Inlines.ABS16(y) < 1E-09f)
			{
				x *= 1E+12f;
				y *= 1E+12f;
			}
			float num = x * x;
			float num2 = y * y;
			if (num < num2)
			{
				float num3 = (num2 + 0.678484f * num) * (num2 + 0.08595542f * num);
				if (num3 != 0f)
				{
					return (0f - x) * y * (num2 + 0.43157974f * num) / num3 + ((y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f));
				}
				if (!(y < 0f))
				{
					return MathF.PI / 2f;
				}
				return -MathF.PI / 2f;
			}
			float num4 = (num + 0.678484f * num2) * (num + 0.08595542f * num2);
			if (num4 != 0f)
			{
				return x * y * (num + 0.43157974f * num2) / num4 + ((y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f)) - ((x * y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f));
			}
			return ((y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f)) - ((x * y < 0f) ? (-MathF.PI / 2f) : (MathF.PI / 2f));
		}

		internal static void tonality_analysis_init(TonalityAnalysisState tonal)
		{
			tonal.Reset();
		}

		internal static void tonality_get_info(TonalityAnalysisState tonal, AnalysisInfo info_out, int len)
		{
			int num = tonal.read_pos;
			int num2 = tonal.write_pos - tonal.read_pos;
			if (num2 < 0)
			{
				num2 += 200;
			}
			if (len > 480 && num != tonal.write_pos)
			{
				num++;
				if (num == 200)
				{
					num = 0;
				}
			}
			if (num == tonal.write_pos)
			{
				num--;
			}
			if (num < 0)
			{
				num = 199;
			}
			info_out.Assign(tonal.info[num]);
			tonal.read_subframe += len / 120;
			while (tonal.read_subframe >= 4)
			{
				tonal.read_subframe -= 4;
				tonal.read_pos++;
			}
			if (tonal.read_pos >= 200)
			{
				tonal.read_pos -= 200;
			}
			num2 = Inlines.IMAX(num2 - 10, 0);
			float num3 = 0f;
			int i;
			for (i = 0; i < 200 - num2; i++)
			{
				num3 += tonal.pmusic[i];
			}
			for (; i < 200; i++)
			{
				num3 += tonal.pspeech[i];
			}
			num3 = num3 * tonal.music_confidence + (1f - num3) * tonal.speech_confidence;
			info_out.music_prob = num3;
		}

		internal static void tonality_analysis<T>(TonalityAnalysisState tonal, CeltMode celt_mode, ReadOnlySpan<T> x, int len, int offset, int c1, int c2, int C, int lsb_depth, Downmix.downmix_func<T> downmix)
		{
			int num = 480;
			int num2 = 240;
			float[] angle = tonal.angle;
			float[] d_angle = tonal.d_angle;
			float[] d2_angle = tonal.d2_angle;
			float[] array = new float[18];
			float[] array2 = new float[18];
			float[] array3 = new float[8];
			float[] array4 = new float[25];
			float num3 = 97.40909f;
			float num4 = 0f;
			float[] array5 = new float[2];
			int num5 = 0;
			float num6 = 0f;
			tonal.last_transition++;
			float num7 = 1f / (float)Inlines.IMIN(20, 1 + tonal.count);
			float num8 = 1f / (float)Inlines.IMIN(50, 1 + tonal.count);
			float num9 = 1f / (float)Inlines.IMIN(1000, 1 + tonal.count);
			if (tonal.count < 4)
			{
				tonal.music_prob = 0.5f;
			}
			FFTState st = celt_mode.mdct.kfft[0];
			if (tonal.count == 0)
			{
				tonal.mem_fill = 240;
			}
			downmix(x, tonal.inmem, tonal.mem_fill, Inlines.IMIN(len, 720 - tonal.mem_fill), offset, c1, c2, C);
			if (tonal.mem_fill + len < 720)
			{
				tonal.mem_fill += len;
				return;
			}
			AnalysisInfo analysisInfo = tonal.info[tonal.write_pos++];
			if (tonal.write_pos >= 200)
			{
				tonal.write_pos -= 200;
			}
			int[] array6 = new int[960];
			int[] array7 = new int[960];
			float[] array8 = new float[240];
			float[] array9 = new float[240];
			for (int i = 0; i < num2; i++)
			{
				float num10 = Tables.analysis_window[i];
				array6[2 * i] = (int)(num10 * (float)tonal.inmem[i]);
				array6[2 * i + 1] = (int)(num10 * (float)tonal.inmem[num2 + i]);
				array6[2 * (num - i - 1)] = (int)(num10 * (float)tonal.inmem[num - i - 1]);
				array6[2 * (num - i - 1) + 1] = (int)(num10 * (float)tonal.inmem[num + num2 - i - 1]);
			}
			Arrays.MemMoveInt(tonal.inmem, 480, 0, 240);
			int num11 = len - (720 - tonal.mem_fill);
			downmix(x, tonal.inmem, 240, num11, offset + 720 - tonal.mem_fill, c1, c2, C);
			tonal.mem_fill = 240 + num11;
			KissFFT.opus_fft(st, array6, array7);
			for (int i = 1; i < num2; i++)
			{
				float x2 = (float)array7[2 * i] + (float)array7[2 * (num - i)];
				float y = (float)array7[2 * i + 1] - (float)array7[2 * (num - i) + 1];
				float x3 = (float)array7[2 * i + 1] + (float)array7[2 * (num - i) + 1];
				float y2 = (float)array7[2 * (num - i)] - (float)array7[2 * i];
				float num12 = 1f / (2f * MathF.PI) * fast_atan2f(y, x2);
				float num13 = num12 - angle[i];
				float num14 = num13 - d_angle[i];
				float num15 = 1f / (2f * MathF.PI) * fast_atan2f(y2, x3);
				float num16 = num15 - num12;
				float num17 = num16 - num13;
				float num18 = num14 - (float)Math.Floor(0.5f + num14);
				array9[i] = Inlines.ABS16(num18);
				num18 *= num18;
				num18 *= num18;
				float num19 = num17 - (float)Math.Floor(0.5f + num17);
				array9[i] += Inlines.ABS16(num19);
				num19 *= num19;
				num19 *= num19;
				float num20 = 0.25f * (d2_angle[i] + 2f * num18 + num19);
				array8[i] = 1f / (1f + 640f * num3 * num20) - 0.015f;
				angle[i] = num15;
				d_angle[i] = num16;
				d2_angle[i] = num19;
			}
			float num21 = 0f;
			float num22 = 0f;
			analysisInfo.activity = 0f;
			float num23 = 0f;
			float num24 = 0f;
			if (tonal.count == 0)
			{
				for (int j = 0; j < 18; j++)
				{
					tonal.lowE[j] = 1E+10f;
					tonal.highE[j] = -1E+10f;
				}
			}
			float num25 = 0f;
			float num26 = 0f;
			for (int j = 0; j < 18; j++)
			{
				float num27 = 0f;
				float num28 = 0f;
				float num29 = 0f;
				for (int i = Tables.tbands[j]; i < Tables.tbands[j + 1]; i++)
				{
					float num30 = (float)array7[2 * i] * (float)array7[2 * i] + (float)array7[2 * (num - i)] * (float)array7[2 * (num - i)] + (float)array7[2 * i + 1] * (float)array7[2 * i + 1] + (float)array7[2 * (num - i) + 1] * (float)array7[2 * (num - i) + 1];
					num30 *= 5.55E-17f;
					num27 += num30;
					num28 += num30 * array8[i];
					num29 += num30 * 2f * (0.5f - array9[i]);
				}
				tonal.E[tonal.E_count][j] = num27;
				num23 += num29 / (1E-15f + num27);
				num26 += (float)Math.Sqrt(num27 + 1E-10f);
				array2[j] = (float)Math.Log(num27 + 1E-10f);
				tonal.lowE[j] = Inlines.MIN32(array2[j], tonal.lowE[j] + 0.01f);
				tonal.highE[j] = Inlines.MAX32(array2[j], tonal.highE[j] - 0.1f);
				if (tonal.highE[j] < tonal.lowE[j] + 1f)
				{
					tonal.highE[j] += 0.5f;
					tonal.lowE[j] -= 0.5f;
				}
				num25 += (array2[j] - tonal.lowE[j]) / (1E-15f + tonal.highE[j] - tonal.lowE[j]);
				float num31;
				float num32 = (num31 = 0f);
				for (int i = 0; i < 8; i++)
				{
					num32 += (float)Math.Sqrt(tonal.E[i][j]);
					num31 += tonal.E[i][j];
				}
				float num33 = Inlines.MIN16(0.99f, num32 / (float)Math.Sqrt(1E-15 + (double)(8f * num31)));
				num33 *= num33;
				num33 *= num33;
				num24 += num33;
				array[j] = Inlines.MAX16(num28 / (1E-15f + num27), num33 * tonal.prev_band_tonality[j]);
				num21 += array[j];
				if (j >= 9)
				{
					num21 -= array[j - 18 + 9];
				}
				num22 = Inlines.MAX16(num22, (1f + 0.03f * (float)(j - 18)) * num21);
				num4 += array[j] * (float)(j - 8);
				tonal.prev_band_tonality[j] = array[j];
			}
			float num34 = 0f;
			num5 = 0;
			num6 = 0f;
			float num35 = 0.00057f / (float)(1 << Inlines.IMAX(0, lsb_depth - 8));
			num35 *= 134217730f;
			num35 *= num35;
			for (int j = 0; j < 21; j++)
			{
				float num36 = 0f;
				int num37 = Tables.extra_bands[j];
				int num38 = Tables.extra_bands[j + 1];
				for (int i = num37; i < num38; i++)
				{
					float num39 = (float)array7[2 * i] * (float)array7[2 * i] + (float)array7[2 * (num - i)] * (float)array7[2 * (num - i)] + (float)array7[2 * i + 1] * (float)array7[2 * i + 1] + (float)array7[2 * (num - i) + 1] * (float)array7[2 * (num - i) + 1];
					num36 += num39;
				}
				num6 = Inlines.MAX32(num6, num36);
				tonal.meanE[j] = Inlines.MAX32((1f - num9) * tonal.meanE[j], num36);
				num36 = Inlines.MAX32(num36, tonal.meanE[j]);
				num34 = Inlines.MAX32(0.05f * num34, num36);
				if ((double)num36 > 0.1 * (double)num34 && num36 * 1E+09f > num6 && num36 > num35 * (float)(num38 - num37))
				{
					num5 = j;
				}
			}
			if (tonal.count <= 2)
			{
				num5 = 20;
			}
			num26 = 20f * (float)Math.Log10(num26);
			tonal.Etracker = Inlines.MAX32(tonal.Etracker - 0.03f, num26);
			tonal.lowECount *= 1f - num8;
			if (num26 < tonal.Etracker - 30f)
			{
				tonal.lowECount += num8;
			}
			for (int i = 0; i < 8; i++)
			{
				float num40 = 0f;
				for (int j = 0; j < 16; j++)
				{
					num40 += Tables.dct_table[i * 16 + j] * array2[j];
				}
				array3[i] = num40;
			}
			num24 /= 18f;
			num25 /= 18f;
			if (tonal.count < 10)
			{
				num25 = 0.5f;
			}
			num23 /= 18f;
			analysisInfo.activity = num23 + (1f - num23) * num25;
			num21 = num22 / 9f;
			num21 = (tonal.prev_tonality = Inlines.MAX16(num21, tonal.prev_tonality * 0.8f));
			num4 /= 64f;
			analysisInfo.tonality_slope = num4;
			tonal.E_count = (tonal.E_count + 1) % 8;
			tonal.count++;
			analysisInfo.tonality = num21;
			for (int i = 0; i < 4; i++)
			{
				array4[i] = -0.12299f * (array3[i] + tonal.mem[i + 24]) + 0.49195f * (tonal.mem[i] + tonal.mem[i + 16]) + 0.69693f * tonal.mem[i + 8] - 1.4349f * tonal.cmean[i];
			}
			for (int i = 0; i < 4; i++)
			{
				tonal.cmean[i] = (1f - num7) * tonal.cmean[i] + num7 * array3[i];
			}
			for (int i = 0; i < 4; i++)
			{
				array4[4 + i] = 0.63246f * (array3[i] - tonal.mem[i + 24]) + 0.31623f * (tonal.mem[i] - tonal.mem[i + 16]);
			}
			for (int i = 0; i < 3; i++)
			{
				array4[8 + i] = 0.53452f * (array3[i] + tonal.mem[i + 24]) - 0.26726f * (tonal.mem[i] + tonal.mem[i + 16]) - 0.53452f * tonal.mem[i + 8];
			}
			if (tonal.count > 5)
			{
				for (int i = 0; i < 9; i++)
				{
					tonal.std[i] = (1f - num7) * tonal.std[i] + num7 * array4[i] * array4[i];
				}
			}
			for (int i = 0; i < 8; i++)
			{
				tonal.mem[i + 24] = tonal.mem[i + 16];
				tonal.mem[i + 16] = tonal.mem[i + 8];
				tonal.mem[i + 8] = tonal.mem[i];
				tonal.mem[i] = array3[i];
			}
			for (int i = 0; i < 9; i++)
			{
				array4[11 + i] = (float)Math.Sqrt(tonal.std[i]);
			}
			array4[20] = analysisInfo.tonality;
			array4[21] = analysisInfo.activity;
			array4[22] = num24;
			array4[23] = analysisInfo.tonality_slope;
			array4[24] = tonal.lowECount;
			MultiLayerPerceptron.mlp_process(Tables.net, array4, array5);
			array5[0] = 0.5f * (array5[0] + 1f);
			array5[0] = 0.01f + 1.21f * array5[0] * array5[0] - 0.23f * (float)Math.Pow(array5[0], 10.0);
			array5[1] = 0.5f * array5[1] + 0.5f;
			array5[0] = array5[1] * array5[0] + (1f - array5[1]) * 0.5f;
			float num41 = 5E-05f * array5[1];
			float num42 = 0.05f;
			float num43 = Inlines.MAX16(0.05f, Inlines.MIN16(0.95f, array5[0]));
			float num44 = Inlines.MAX16(0.05f, Inlines.MIN16(0.95f, tonal.music_prob));
			num42 = 0.01f + 0.05f * Inlines.ABS16(num43 - num44) / (num43 * (1f - num44) + num44 * (1f - num43));
			float num45 = (1f - tonal.music_prob) * (1f - num41) + tonal.music_prob * num41;
			float num46 = tonal.music_prob * (1f - num41) + (1f - tonal.music_prob) * num41;
			num45 *= (float)Math.Pow(1f - array5[0], num42);
			num46 *= (float)Math.Pow(array5[0], num42);
			tonal.music_prob = num46 / (num45 + num46);
			analysisInfo.music_prob = tonal.music_prob;
			float num47 = 1E-20f;
			float num48 = (float)Math.Pow(1f - array5[0], num42);
			float num49 = (float)Math.Pow(array5[0], num42);
			if (tonal.count == 1)
			{
				tonal.pspeech[0] = 0.5f;
				tonal.pmusic[0] = 0.5f;
			}
			float num50 = tonal.pspeech[0] + tonal.pspeech[1];
			float num51 = tonal.pmusic[0] + tonal.pmusic[1];
			tonal.pspeech[0] = num50 * (1f - num41) * num48;
			tonal.pmusic[0] = num51 * (1f - num41) * num49;
			for (int i = 1; i < 199; i++)
			{
				tonal.pspeech[i] = tonal.pspeech[i + 1] * num48;
				tonal.pmusic[i] = tonal.pmusic[i + 1] * num49;
			}
			tonal.pspeech[199] = num51 * num41 * num48;
			tonal.pmusic[199] = num50 * num41 * num49;
			for (int i = 0; i < 200; i++)
			{
				num47 += tonal.pspeech[i] + tonal.pmusic[i];
			}
			num47 = 1f / num47;
			for (int i = 0; i < 200; i++)
			{
				tonal.pspeech[i] *= num47;
				tonal.pmusic[i] *= num47;
			}
			num47 = tonal.pmusic[0];
			for (int i = 1; i < 200; i++)
			{
				num47 += tonal.pspeech[i];
			}
			if ((double)array5[1] > 0.75)
			{
				if ((double)tonal.music_prob > 0.9)
				{
					float num52 = 1f / (float)(++tonal.music_confidence_count);
					tonal.music_confidence_count = Inlines.IMIN(tonal.music_confidence_count, 500);
					tonal.music_confidence += num52 * Inlines.MAX16(-0.2f, array5[0] - tonal.music_confidence);
				}
				if ((double)tonal.music_prob < 0.1)
				{
					float num53 = 1f / (float)(++tonal.speech_confidence_count);
					tonal.speech_confidence_count = Inlines.IMIN(tonal.speech_confidence_count, 500);
					tonal.speech_confidence += num53 * Inlines.MIN16(0.2f, array5[0] - tonal.speech_confidence);
				}
			}
			else
			{
				if (tonal.music_confidence_count == 0)
				{
					tonal.music_confidence = 0.9f;
				}
				if (tonal.speech_confidence_count == 0)
				{
					tonal.speech_confidence = 0.1f;
				}
			}
			if (tonal.last_music != ((tonal.music_prob > 0.5f) ? 1 : 0))
			{
				tonal.last_transition = 0;
			}
			tonal.last_music = ((tonal.music_prob > 0.5f) ? 1 : 0);
			analysisInfo.bandwidth = num5;
			analysisInfo.noisiness = num23;
			analysisInfo.valid = 1;
		}

		internal static void run_analysis<T>(TonalityAnalysisState analysis, CeltMode celt_mode, ReadOnlySpan<T> analysis_pcm, int analysis_frame_size, int frame_size, int c1, int c2, int C, int Fs, int lsb_depth, Downmix.downmix_func<T> downmix, AnalysisInfo analysis_info)
		{
			if (!analysis_pcm.IsEmpty)
			{
				analysis_frame_size = Inlines.IMIN(195 * Fs / 100, analysis_frame_size);
				int num = analysis_frame_size - analysis.analysis_offset;
				int num2 = analysis.analysis_offset;
				do
				{
					tonality_analysis(analysis, celt_mode, analysis_pcm, Inlines.IMIN(480, num), num2, c1, c2, C, lsb_depth, downmix);
					num2 += 480;
					num -= 480;
				}
				while (num > 0);
				analysis.analysis_offset = analysis_frame_size;
				analysis.analysis_offset -= frame_size;
			}
			analysis_info.valid = 0;
			tonality_get_info(analysis, analysis_info, frame_size);
		}
	}
	internal static class CodecHelpers
	{
		private const int MAX_DYNAMIC_FRAMESIZE = 24;

		internal static byte gen_toc(OpusMode mode, int framerate, OpusBandwidth bandwidth, int channels)
		{
			int num = 0;
			while (framerate < 400)
			{
				framerate <<= 1;
				num++;
			}
			byte b;
			switch (mode)
			{
			case OpusMode.MODE_SILK_ONLY:
				b = (byte)((int)(bandwidth - 1101) << 5);
				b |= (byte)(num - 2 << 3);
				break;
			case OpusMode.MODE_CELT_ONLY:
			{
				int num2 = (int)(bandwidth - 1102);
				if (num2 < 0)
				{
					num2 = 0;
				}
				b = 128;
				b |= (byte)(num2 << 5);
				b |= (byte)(num << 3);
				break;
			}
			default:
				b = 96;
				b |= (byte)((int)(bandwidth - 1104) << 4);
				b |= (byte)(num - 2 << 3);
				break;
			}
			return (byte)(b | (byte)(((channels == 2) ? 1u : 0u) << 2));
		}

		internal static void hp_cutoff(ReadOnlySpan<short> input, int input_ptr, int cutoff_Hz, Span<short> output, int output_ptr, int[] hp_mem, int len, int channels, int Fs)
		{
			int[] array = new int[3];
			int[] array2 = new int[2];
			int num = Inlines.silk_DIV32_16(Inlines.silk_SMULBB(2471, cutoff_Hz), Fs / 1000);
			int num2 = (array[0] = 268435456 - Inlines.silk_MUL(471, num));
			array[1] = Inlines.silk_LSHIFT(-num2, 1);
			array[2] = num2;
			int num3 = Inlines.silk_RSHIFT(num2, 6);
			array2[0] = Inlines.silk_SMULWW(num3, Inlines.silk_SMULWW(num, num) - 8388608);
			array2[1] = Inlines.silk_SMULWW(num3, num3);
			Filters.silk_biquad_alt(input, input_ptr, array, array2, hp_mem, 0, output, output_ptr, len, channels);
			if (channels == 2)
			{
				Filters.silk_biquad_alt(input, input_ptr + 1, array, array2, hp_mem, 2, output, output_ptr + 1, len, channels);
			}
		}

		internal static void dc_reject(ReadOnlySpan<short> input, int input_ptr, int cutoff_Hz, Span<short> output, int output_ptr, int[] hp_mem, int len, int channels, int Fs)
		{
			int shift = Inlines.celt_ilog2(Fs / (cutoff_Hz * 3));
			for (int i = 0; i < channels; i++)
			{
				for (int j = 0; j < len; j++)
				{
					int num = Inlines.SHL32(Inlines.EXTEND32(input[channels * j + i + input_ptr]), 15);
					int num2 = num - hp_mem[2 * i];
					hp_mem[2 * i] += Inlines.PSHR32(num - hp_mem[2 * i], shift);
					int a = num2 - hp_mem[2 * i + 1];
					hp_mem[2 * i + 1] += Inlines.PSHR32(num2 - hp_mem[2 * i + 1], shift);
					output[channels * j + i + output_ptr] = Inlines.EXTRACT16(Inlines.SATURATE(Inlines.PSHR32(a, 15), 32767));
				}
			}
		}

		internal static void stereo_fade(short[] pcm_buf, int g1, int g2, int overlap48, int frame_size, int channels, int[] window, int Fs)
		{
			int num = 48000 / Fs;
			int num2 = overlap48 / num;
			g1 = 32767 - g1;
			g2 = 32767 - g2;
			int i;
			for (i = 0; i < num2; i++)
			{
				int num3 = Inlines.MULT16_16_Q15(window[i * num], window[i * num]);
				int a = Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num3, g2), 32767 - num3, g1), 15);
				int b = Inlines.EXTRACT16(Inlines.HALF32(pcm_buf[i * channels] - pcm_buf[i * channels + 1]));
				b = Inlines.MULT16_16_Q15(a, b);
				pcm_buf[i * channels] = (short)(pcm_buf[i * channels] - b);
				pcm_buf[i * channels + 1] = (short)(pcm_buf[i * channels + 1] + b);
			}
			for (; i < frame_size; i++)
			{
				int b2 = Inlines.EXTRACT16(Inlines.HALF32(pcm_buf[i * channels] - pcm_buf[i * channels + 1]));
				b2 = Inlines.MULT16_16_Q15(g2, b2);
				pcm_buf[i * channels] = (short)(pcm_buf[i * channels] - b2);
				pcm_buf[i * channels + 1] = (short)(pcm_buf[i * channels + 1] + b2);
			}
		}

		internal static void gain_fade(short[] buffer, int buf_ptr, int g1, int g2, int overlap48, int frame_size, int channels, int[] window, int Fs)
		{
			int num = 48000 / Fs;
			int num2 = overlap48 / num;
			if (channels == 1)
			{
				for (int i = 0; i < num2; i++)
				{
					int num3 = Inlines.MULT16_16_Q15(window[i * num], window[i * num]);
					int a = Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num3, g2), 32767 - num3, g1), 15);
					buffer[buf_ptr + i] = (short)Inlines.MULT16_16_Q15(a, buffer[buf_ptr + i]);
				}
			}
			else
			{
				for (int i = 0; i < num2; i++)
				{
					int num4 = Inlines.MULT16_16_Q15(window[i * num], window[i * num]);
					int a2 = Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num4, g2), 32767 - num4, g1), 15);
					buffer[buf_ptr + i * 2] = (short)Inlines.MULT16_16_Q15(a2, buffer[buf_ptr + i * 2]);
					buffer[buf_ptr + i * 2 + 1] = (short)Inlines.MULT16_16_Q15(a2, buffer[buf_ptr + i * 2 + 1]);
				}
			}
			int num5 = 0;
			do
			{
				for (int i = num2; i < frame_size; i++)
				{
					buffer[buf_ptr + i * channels + num5] = (short)Inlines.MULT16_16_Q15(g2, buffer[buf_ptr + i * channels + num5]);
				}
			}
			while (++num5 < channels);
		}

		internal static float transient_boost(Span<float> E, int E_ptr, float[] E_1, int LM, int maxM)
		{
			float num = 0f;
			float num2 = 0f;
			int num3 = Inlines.IMIN(maxM, (1 << LM) + 1);
			for (int i = E_ptr; i < num3 + E_ptr; i++)
			{
				num += E[i];
				num2 += E_1[i];
			}
			float num4 = num * num2 / (float)(num3 * num3);
			return Inlines.MIN16(1f, (float)Math.Sqrt(Inlines.MAX16(0f, 0.05f * (num4 - 2f))));
		}

		internal static int transient_viterbi(float[] E, float[] E_1, int N, int frame_cost, int rate)
		{
			float[][] array = Arrays.InitTwoDimensionalArray<float>(24, 16);
			int[][] array2 = Arrays.InitTwoDimensionalArray<int>(24, 16);
			float num = ((rate < 80) ? 0f : ((rate <= 160) ? (((float)rate - 80f) / 80f) : 1f));
			for (int i = 0; i < 16; i++)
			{
				array2[0][i] = -1;
				array[0][i] = 1E+10f;
			}
			for (int i = 0; i < 4; i++)
			{
				array[0][1 << i] = (float)(frame_cost + rate * (1 << i)) * (1f + num * transient_boost(E, 0, E_1, i, N + 1));
				array2[0][1 << i] = i;
			}
			for (int i = 1; i < N; i++)
			{
				for (int j = 2; j < 16; j++)
				{
					array[i][j] = array[i - 1][j - 1];
					array2[i][j] = j - 1;
				}
				for (int j = 0; j < 4; j++)
				{
					array2[i][1 << j] = 1;
					float num2 = array[i - 1][1];
					for (int k = 1; k < 4; k++)
					{
						float num3 = array[i - 1][(1 << k + 1) - 1];
						if (num3 < num2)
						{
							array2[i][1 << j] = (1 << k + 1) - 1;
							num2 = num3;
						}
					}
					float num4 = (float)(frame_cost + rate * (1 << j)) * (1f + num * transient_boost(E, i, E_1, j, N - i + 1));
					array[i][1 << j] = num2;
					if (N - i < 1 << j)
					{
						array[i][1 << j] += num4 * (float)(N - i) / (float)(1 << j);
					}
					else
					{
						array[i][1 << j] += num4;
					}
				}
			}
			int num5 = 1;
			float num6 = array[N - 1][1];
			for (int i = 2; i < 16; i++)
			{
				if (array[N - 1][i] < num6)
				{
					num6 = array[N - 1][i];
					num5 = i;
				}
			}
			for (int i = N - 1; i >= 0; i--)
			{
				num5 = array2[i][num5];
			}
			return num5;
		}

		internal static int optimize_framesize<T>(ReadOnlySpan<T> x, int len, int C, int Fs, int bitrate, int tonality, float[] mem, int buffering, Downmix.downmix_func<T> downmix)
		{
			float[] array = new float[28];
			float[] array2 = new float[27];
			int num = 0;
			int num2 = Fs / 400;
			int[] array3 = new int[num2];
			array[0] = mem[0];
			array2[0] = 1f / (1f + mem[0]);
			int num3;
			int num4;
			if (buffering != 0)
			{
				num3 = 2 * num2 - buffering;
				len -= num3;
				array[1] = mem[1];
				array2[1] = 1f / (1f + mem[1]);
				array[2] = mem[2];
				array2[2] = 1f / (1f + mem[2]);
				num4 = 3;
			}
			else
			{
				num4 = 1;
				num3 = 0;
			}
			int num5 = Inlines.IMIN(len / num2, 24);
			int num6 = 0;
			int i;
			for (i = 0; i < num5; i++)
			{
				float num7 = 1f;
				downmix(x, array3, 0, num2, i * num2 + num3, 0, -2, C);
				if (i == 0)
				{
					num6 = array3[0];
				}
				for (int j = 0; j < num2; j++)
				{
					int num8 = array3[j];
					num7 += (float)(num8 - num6) * (float)(num8 - num6);
					num6 = num8;
				}
				array[i + num4] = num7;
				array2[i + num4] = 1f / num7;
			}
			array[i + num4] = array[i + num4 - 1];
			if (buffering != 0)
			{
				num5 = Inlines.IMIN(24, num5 + 2);
			}
			num = transient_viterbi(array, array2, num5, (int)((1f + 0.5f * (float)tonality) * (float)(60 * C + 40)), bitrate / 400);
			mem[0] = array[1 << num];
			if (buffering != 0)
			{
				mem[1] = array[(1 << num) + 1];
				mem[2] = array[(1 << num) + 2];
			}
			return num;
		}

		internal static int frame_size_select(int frame_size, OpusFramesize variable_duration, int Fs)
		{
			if (frame_size < Fs / 400)
			{
				return -1;
			}
			int num;
			switch (variable_duration)
			{
			case OpusFramesize.OPUS_FRAMESIZE_ARG:
				num = frame_size;
				break;
			case OpusFramesize.OPUS_FRAMESIZE_VARIABLE:
				num = Fs / 50;
				break;
			case OpusFramesize.OPUS_FRAMESIZE_2_5_MS:
			case OpusFramesize.OPUS_FRAMESIZE_5_MS:
			case OpusFramesize.OPUS_FRAMESIZE_10_MS:
			case OpusFramesize.OPUS_FRAMESIZE_20_MS:
			case OpusFramesize.OPUS_FRAMESIZE_40_MS:
			case OpusFramesize.OPUS_FRAMESIZE_60_MS:
				num = Inlines.IMIN(3 * Fs / 50, Fs / 400 << (int)(variable_duration - 5001));
				break;
			default:
				return -1;
			}
			if (num > frame_size)
			{
				return -1;
			}
			if (400 * num != Fs && 200 * num != Fs && 100 * num != Fs && 50 * num != Fs && 25 * num != Fs && 50 * num != 3 * Fs)
			{
				return -1;
			}
			return num;
		}

		internal static int compute_frame_size<T>(ReadOnlySpan<T> analysis_pcm, int frame_size, OpusFramesize variable_duration, int C, int Fs, int bitrate_bps, int delay_compensation, Downmix.downmix_func<T> downmix, float[] subframe_mem, bool analysis_enabled)
		{
			if (analysis_enabled && variable_duration == OpusFramesize.OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs / 200)
			{
				int num = 3;
				num = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps, 0, subframe_mem, delay_compensation, downmix);
				while (Fs / 400 << num > frame_size)
				{
					num--;
				}
				frame_size = Fs / 400 << num;
			}
			else
			{
				frame_size = frame_size_select(frame_size, variable_duration, Fs);
			}
			if (frame_size < 0)
			{
				return -1;
			}
			return frame_size;
		}

		internal static int compute_stereo_width(ReadOnlySpan<short> pcm, int pcm_ptr, int frame_size, int Fs, StereoWidthState mem)
		{
			int num = Fs / frame_size;
			int a = 32767 - 819175 / Inlines.IMAX(50, num);
			int num3;
			int num2;
			int num4 = (num3 = (num2 = 0));
			for (int i = 0; i < frame_size - 3; i += 4)
			{
				int num5 = 0;
				int num6 = 0;
				int num7 = 0;
				int num8 = pcm_ptr + 2 * i;
				int num9 = pcm[num8];
				int num10 = pcm[num8 + 1];
				num5 = Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 = Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 = Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num9 = pcm[num8 + 2];
				num10 = pcm[num8 + 3];
				num5 += Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 += Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 += Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num9 = pcm[num8 + 4];
				num10 = pcm[num8 + 5];
				num5 += Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 += Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 += Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num9 = pcm[num8 + 6];
				num10 = pcm[num8 + 7];
				num5 += Inlines.SHR32(Inlines.MULT16_16(num9, num9), 2);
				num6 += Inlines.SHR32(Inlines.MULT16_16(num9, num10), 2);
				num7 += Inlines.SHR32(Inlines.MULT16_16(num10, num10), 2);
				num4 += Inlines.SHR32(num5, 10);
				num3 += Inlines.SHR32(num6, 10);
				num2 += Inlines.SHR32(num7, 10);
			}
			mem.XX += Inlines.MULT16_32_Q15(a, num4 - mem.XX);
			mem.XY += Inlines.MULT16_32_Q15(a, num3 - mem.XY);
			mem.YY += Inlines.MULT16_32_Q15(a, num2 - mem.YY);
			mem.XX = Inlines.MAX32(0, mem.XX);
			mem.XY = Inlines.MAX32(0, mem.XY);
			mem.YY = Inlines.MAX32(0, mem.YY);
			if (Inlines.MAX32(mem.XX, mem.YY) > 210)
			{
				int num11 = Inlines.celt_sqrt(mem.XX);
				int num12 = Inlines.celt_sqrt(mem.YY);
				int num13 = Inlines.celt_sqrt(num11);
				int num14 = Inlines.celt_sqrt(num12);
				mem.XY = Inlines.MIN32(mem.XY, num11 * num12);
				int num15 = Inlines.SHR32(Inlines.frac_div32(mem.XY, 1 + Inlines.MULT16_16(num11, num12)), 16);
				int b = 32767 * Inlines.ABS16(num13 - num14) / (1 + num13 + num14);
				int num16 = Inlines.MULT16_16_Q15(Inlines.celt_sqrt(1073741824 - Inlines.MULT16_16(num15, num15)), b);
				mem.smoothed_width += (num16 - mem.smoothed_width) / num;
				mem.max_follower = Inlines.MAX16(mem.max_follower - 655 / num, mem.smoothed_width);
			}
			else
			{
				int num16 = 0;
				int num15 = 32767;
				int b = 0;
			}
			return Inlines.EXTRACT16(Inlines.MIN32(32767, 20 * mem.max_follower));
		}

		internal static void smooth_fade(Span<short> in1, int in1_ptr, Span<short> in2, int in2_ptr, Span<short> output, int output_ptr, int overlap, int channels, int[] window, int Fs)
		{
			int num = 48000 / Fs;
			for (int i = 0; i < channels; i++)
			{
				for (int j = 0; j < overlap; j++)
				{
					int num2 = Inlines.MULT16_16_Q15(window[j * num], window[j * num]);
					output[output_ptr + j * channels + i] = (short)Inlines.SHR32(Inlines.MAC16_16(Inlines.MULT16_16(num2, in2[in2_ptr + j * channels + i]), 32767 - num2, in1[in1_ptr + j * channels + i]), 15);
				}
			}
		}

		internal static string opus_strerror(int error)
		{
			string[] array = new string[8] { "success", "invalid argument", "buffer too small", "internal error", "corrupted stream", "request not implemented", "invalid state", "memory allocation failed" };
			if (error > 0 || error < -7)
			{
				return "unknown error";
			}
			return array[-error];
		}

		internal static string GetVersionString()
		{
			return "Concentus 2.1.2";
		}
	}
	internal static class Downmix
	{
		internal delegate void downmix_func<T>(ReadOnlySpan<T> _x, Span<int> sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C);

		internal static void downmix_float(ReadOnlySpan<float> x, Span<int> sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C)
		{
			for (int i = 0; i < subframe; i++)
			{
				sub[sub_ptr + i] = Inlines.FLOAT2INT16(x[(i + offset) * C + c1]);
			}
			if (c2 > -1)
			{
				for (int i = 0; i < subframe; i++)
				{
					sub[sub_ptr + i] += Inlines.FLOAT2INT16(x[(i + offset) * C + c2]);
				}
			}
			else if (c2 == -2)
			{
				for (int j = 1; j < C; j++)
				{
					int num = j;
					for (int i = 0; i < subframe; i++)
					{
						sub[sub_ptr + i] += Inlines.FLOAT2INT16(x[(i + offset) * C + num]);
					}
				}
			}
			int num2 = 4096;
			num2 = ((C != -2) ? (num2 / 2) : (num2 / C));
			for (int i = 0; i < subframe; i++)
			{
				sub[sub_ptr + i] *= num2;
			}
		}

		internal static void downmix_int(ReadOnlySpan<short> x, Span<int> sub, int sub_ptr, int subframe, int offset, int c1, int c2, int C)
		{
			for (int i = 0; i < subframe; i++)
			{
				sub[i + sub_ptr] = x[(i + offset) * C + c1];
			}
			if (c2 > -1)
			{
				for (int i = 0; i < subframe; i++)
				{
					sub[i + sub_ptr] += x[(i + offset) * C + c2];
				}
			}
			else if (c2 == -2)
			{
				for (int j = 1; j < C; j++)
				{
					for (int i = 0; i < subframe; i++)
					{
						sub[i + sub_ptr] += x[(i + offset) * C + j];
					}
				}
			}
			int num = 4096;
			num = ((C != -2) ? (num / 2) : (num / C));
			for (int i = 0; i < subframe; i++)
			{
				sub[i + sub_ptr] *= num;
			}
		}
	}
	internal static class MultiLayerPerceptron
	{
		private const int MAX_NEURONS = 100;

		internal static float tansig_approx(float x)
		{
			float num = 1f;
			if (!(x < 8f))
			{
				return 1f;
			}
			if (!(x > -8f))
			{
				return -1f;
			}
			if (x < 0f)
			{
				x = 0f - x;
				num = -1f;
			}
			int num2 = (int)Math.Floor(0.5f + 25f * x);
			x -= 0.04f * (float)num2;
			float num3 = Tables.tansig_table[num2];
			float num4 = 1f - num3 * num3;
			num3 += x * num4 * (1f - num3 * x);
			return num * num3;
		}

		internal static void mlp_process(MLP m, float[] input, float[] output)
		{
			float[] array = new float[100];
			float[] weights = m.weights;
			int num = 0;
			for (int i = 0; i < m.topo[1]; i++)
			{
				float num2 = weights[num];
				num++;
				for (int j = 0; j < m.topo[0]; j++)
				{
					num2 += input[j] * weights[num];
					num++;
				}
				array[i] = tansig_approx(num2);
			}
			for (int i = 0; i < m.topo[2]; i++)
			{
				float num3 = weights[num];
				num++;
				for (int k = 0; k < m.topo[1]; k++)
				{
					num3 += array[k] * weights[num];
					num++;
				}
				output[i] = tansig_approx(num3);
			}
		}
	}
	internal static class OpusCompare
	{
		private const int NBANDS = 21;

		private const int NFREQS = 240;

		private const int TEST_WIN_SIZE = 480;

		private const int TEST_WIN_STEP = 120;

		private static readonly int[] BANDS = new int[22]
		{
			0, 2, 4, 6, 8, 10, 12, 14, 16, 20,
			24, 28, 32, 40, 48, 56, 68, 80, 96, 120,
			156, 200
		};

		private static void band_energy(Pointer<float> _out, Pointer<float> _ps, Pointer<int> _bands, int _nbands, Pointer<float> _in, int _nchannels, int _nframes, int _window_sz, int _step, int _downsample)
		{
			Pointer<float> pointer = Concentus.Common.CPlusPlus.Pointer.Malloc<float>((3 + _nchannels) * _window_sz);
			Pointer<float> pointer2 = pointer.Point(_window_sz);
			Pointer<float> pointer3 = pointer2.Point(_window_sz);
			Pointer<float> pointer4 = pointer3.Point(_window_sz);
			int num = _window_sz / 2;
			for (int i = 0; i < _window_sz; i++)
			{
				pointer[i] = (float)(0.5 - 0.5 * Math.Cos(Math.PI * 2.0 / (double)(_window_sz - 1) * (double)i));
			}
			for (int i = 0; i < _window_sz; i++)
			{
				pointer2[i] = (float)Math.Cos(Math.PI * 2.0 / (double)_window_sz * (double)i);
			}
			for (int i = 0; i < _window_sz; i++)
			{
				pointer3[i] = (float)Math.Sin(Math.PI * 2.0 / (double)_window_sz * (double)i);
			}
			for (int j = 0; j < _nframes; j++)
			{
				for (int k = 0; k < _nchannels; k++)
				{
					for (int l = 0; l < _window_sz; l++)
					{
						pointer4[k * _window_sz + l] = pointer[l] * _in[(j * _step + l) * _nchannels + k];
					}
				}
				int i;
				for (int m = (i = 0); m < _nbands; m++)
				{
					float[] array = new float[2];
					for (; i < _bands[m + 1]; i++)
					{
						for (int k = 0; k < _nchannels; k++)
						{
							int num2 = 0;
							float num3;
							float num4 = (num3 = 0f);
							for (int l = 0; l < _window_sz; l++)
							{
								num4 += pointer2[num2] * pointer4[k * _window_sz + l];
								num3 -= pointer3[num2] * pointer4[k * _window_sz + l];
								num2 += i;
								if (num2 >= _window_sz)
								{
									num2 -= _window_sz;
								}
							}
							num4 *= (float)_downsample;
							num3 *= (float)_downsample;
							_ps[(j * num + i) * _nchannels + k] = num4 * num4 + num3 * num3 + 100000f;
							array[k] += _ps[(j * num + i) * _nchannels + k];
						}
					}
					if (_out != null)
					{
						_out[(j * _nbands + m) * _nchannels] = array[0] / (float)(_bands[m + 1] - _bands[m]);
						if (_nchannels == 2)
						{
							_out[(j * _nbands + m) * _nchannels + 1] = array[1] / (float)(_bands[m + 1] - _bands[m]);
						}
					}
				}
			}
		}

		internal static float compare(float[] x, float[] y, int nchannels, int rate = 48000)
		{
			int num = x.Length;
			int num2 = y.Length;
			int num3 = 21;
			int num4 = 240;
			if (rate != 8000 && rate != 12000 && rate != 16000 && rate != 24000 && rate != 48000)
			{
				throw new ArgumentException("Sampling rate must be 8000, 12000, 16000, 24000, or 48000\n");
			}
			int num5;
			if (rate != 48000)
			{
				num5 = 48000 / rate;
				switch (rate)
				{
				case 8000:
					num3 = 13;
					break;
				case 12000:
					num3 = 15;
					break;
				case 16000:
					num3 = 17;
					break;
				case 24000:
					num3 = 19;
					break;
				}
				num4 = 240 / num5;
			}
			else
			{
				num5 = 1;
			}
			if (num != num2 * num5)
			{
				throw new ArgumentException("Sample counts do not match");
			}
			if (num < 480)
			{
				throw new ArgumentException("Insufficient sample data");
			}
			int num6 = (num - 480 + 120) / 120;
			Pointer<float> pointer = Concentus.Common.CPlusPlus.Pointer.Malloc<float>(num6 * 21 * nchannels);
			Pointer<float> pointer2 = Concentus.Common.CPlusPlus.Pointer.Malloc<float>(num6 * 240 * nchannels);
			Pointer<float> pointer3 = Concentus.Common.CPlusPlus.Pointer.Malloc<float>(num6 * num4 * nchannels);
			band_energy(pointer, pointer2, BANDS.GetPointer(), 21, x.GetPointer(), nchannels, num6, 480, 120, 1);
			band_energy(null, pointer3, BANDS.GetPointer(), num3, y.GetPointer(), nchannels, num6, 480 / num5, 120 / num5, num5);
			for (int i = 0; i < num6; i++)
			{
				int j;
				for (j = 1; j < 21; j++)
				{
					for (int k = 0; k < nchannels; k++)
					{
						pointer[(i * 21 + j) * nchannels + k] += 0.1f * pointer[(i * 21 + j - 1) * nchannels + k];
					}
				}
				j = 20;
				while (j-- > 0)
				{
					for (int k = 0; k < nchannels; k++)
					{
						pointer[(i * 21 + j) * nchannels + k] += 0.03f * pointer[(i * 21 + j + 1) * nchannels + k];
					}
				}
				if (i > 0)
				{
					for (j = 0; j < 21; j++)
					{
						for (int k = 0; k < nchannels; k++)
						{
							pointer[(i * 21 + j) * nchannels + k] += 0.5f * pointer[((i - 1) * 21 + j) * nchannels + k];
						}
					}
				}
				if (nchannels == 2)
				{
					for (j = 0; j < 21; j++)
					{
						float num7 = pointer[(i * 21 + j) * nchannels];
						float num8 = pointer[(i * 21 + j) * nchannels + 1];
						pointer[(i * 21 + j) * nchannels] += 0.01f * num8;
						pointer[(i * 21 + j) * nchannels + 1] += 0.01f * num7;
					}
				}
				for (j = 0; j < num3; j++)
				{
					for (int l = BANDS[j]; l < BANDS[j + 1]; l++)
					{
						for (int k = 0; k < nchannels; k++)
						{
							pointer2[(i * 240 + l) * nchannels + k] += 0.1f * pointer[(i * 21 + j) * nchannels + k];
							pointer3[(i * num4 + l) * nchannels + k] += 0.1f * pointer[(i * 21 + j) * nchannels + k];
						}
					}
				}
			}
			for (int j = 0; j < num3; j++)
			{
				for (int l = BANDS[j]; l < BANDS[j + 1]; l++)
				{
					for (int k = 0; k < nchannels; k++)
					{
						float num9 = pointer2[l * nchannels + k];
						float num10 = pointer3[l * nchannels + k];
						for (int i = 1; i < num6; i++)
						{
							float num11 = pointer2[(i * 240 + l) * nchannels + k];
							float num12 = pointer3[(i * num4 + l) * nchannels + k];
							pointer2[(i * 240 + l) * nchannels + k] += num9;
							pointer3[(i * num4 + l) * nchannels + k] += num10;
							num9 = num11;
							num10 = num12;
						}
					}
				}
			}
			int num13 = rate switch
			{
				48000 => BANDS[21], 
				12000 => BANDS[num3], 
				_ => BANDS[num3] - 3, 
			};
			double num14 = 0.0;
			for (int i = 0; i < num6; i++)
			{
				double num15 = 0.0;
				for (int j = 0; j < num3; j++)
				{
					double num16 = 0.0;
					for (int l = BANDS[j]; l < BANDS[j + 1] && l < num13; l++)
					{
						for (int k = 0; k < nchannels; k++)
						{
							float num17 = pointer3[(i * num4 + l) * nchannels + k] / pointer2[(i * 240 + l) * nchannels + k];
							float num18 = num17 - (float)Math.Log(num17) - 1f;
							if (l >= 79 && l <= 81)
							{
								num18 *= 0.1f;
							}
							if (l == 80)
							{
								num18 *= 0.1f;
							}
							num16 += (double)num18;
						}
					}
					num16 /= (double)((BANDS[j + 1] - BANDS[j]) * nchannels);
					num15 += num16 * num16;
				}
				num15 /= 21.0;
				num15 *= num15;
				num14 += num15 * num15;
			}
			num14 = Math.Pow(num14 / (double)num6, 0.0625);
			float result = (float)(100.0 * (1.0 - 0.5 * Math.Log(1.0 + num14) / Math.Log(1.13)));
			_ = 0f;
			return result;
		}
	}
	internal static class OpusConstants
	{
		internal const int OPUS_AUTO = -1000;

		internal const int OPUS_BITRATE_MAX = -1;

		internal const int NB_FRAMES = 8;

		internal const int NB_TBANDS = 18;

		internal const int NB_TOT_BANDS = 21;

		internal const int NB_TONAL_SKIP_BANDS = 9;

		internal const int ANALYSIS_BUF_SIZE = 720;

		internal const int DETECT_SIZE = 200;

		internal const int MAX_ENCODER_BUFFER = 480;
	}
	public class OpusException : Exception
	{
		public int OpusErrorCode { get; private set; }

		internal OpusException()
			: base("Unknown error")
		{
			OpusErrorCode = -100;
		}

		internal OpusException(string message)
			: base(message)
		{
			OpusErrorCode = -100;
		}

		internal OpusException(int opusError)
			: base(CodecHelpers.opus_strerror(opusError))
		{
			OpusErrorCode = opusError;
		}

		internal OpusException(string message, int opusError)
			: base(message)
		{
			OpusErrorCode = opusError;
		}
	}
	internal static class OpusMultistream
	{
		internal static int validate_layout(ChannelLayout layout)
		{
			int num = layout.nb_streams + layout.nb_coupled_streams;
			if (num > 255)
			{
				return 0;
			}
			for (int i = 0; i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] >= num && layout.mapping[i] != byte.MaxValue)
				{
					return 0;
				}
			}
			return 1;
		}

		internal static int get_left_channel(ChannelLayout layout, int stream_id, int prev)
		{
			for (int i = ((prev >= 0) ? (prev + 1) : 0); i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] == stream_id * 2)
				{
					return i;
				}
			}
			return -1;
		}

		internal static int get_right_channel(ChannelLayout layout, int stream_id, int prev)
		{
			for (int i = ((prev >= 0) ? (prev + 1) : 0); i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] == stream_id * 2 + 1)
				{
					return i;
				}
			}
			return -1;
		}

		internal static int get_mono_channel(ChannelLayout layout, int stream_id, int prev)
		{
			for (int i = ((prev >= 0) ? (prev + 1) : 0); i < layout.nb_channels; i++)
			{
				if (layout.mapping[i] == stream_id + layout.nb_coupled_streams)
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal static class Tables
	{
		internal static readonly float[] dct_table = new float[128]
		{
			0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f,
			0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.351851f, 0.33833f, 0.311806f, 0.2733f,
			0.224292f, 0.166664f, 0.102631f, 0.034654f, -0.034654f, -0.102631f, -0.166664f, -0.224292f, -0.2733f, -0.311806f,
			-0.33833f, -0.351851f, 0.34676f, 0.293969f, 0.196424f, 0.068975f, -0.068975f, -0.196424f, -0.293969f, -0.34676f,
			-0.34676f, -0.293969f, -0.196424f, -0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.34676f, 0.33833f, 0.224292f,
			0.034654f, -0.166664f, -0.311806f, -0.351851f, -0.2733f, -0.102631f, 0.102631f, 0.2733f, 0.351851f, 0.311806f,
			0.166664f, -0.034654f, -0.224292f, -0.33833f, 0.326641f, 0.135299f, -0.135299f, -0.326641f, -0.326641f, -0.135299f,
			0.135299f, 0.326641f, 0.326641f, 0.135299f, -0.135299f, -0.326641f, -0.326641f, -0.135299f, 0.135299f, 0.326641f,
			0.311806f, 0.034654f, -0.2733f, -0.33833f, -0.102631f, 0.224292f, 0.351851f, 0.166664f, -0.166664f, -0.351851f,
			-0.224292f, 0.102631f, 0.33833f, 0.2733f, -0.034654f, -0.311806f, 0.293969f, -0.068975f, -0.34676f, -0.196424f,
			0.196424f, 0.34676f, 0.068975f, -0.293969f, -0.293969f, 0.068975f, 0.34676f, 0.196424f, -0.196424f, -0.34676f,
			-0.068975f, 0.293969f, 0.2733f, -0.166664f, -0.33833f, 0.034654f, 0.351851f, 0.102631f, -0.311806f, -0.224292f,
			0.224292f, 0.311806f, -0.102631f, -0.351851f, -0.034654f, 0.33833f, 0.166664f, -0.2733f
		};

		internal static readonly float[] analysis_window = new float[240]
		{
			4.3E-05f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f, 0.003466f, 0.004278f,
			0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f, 0.012329f, 0.013815f, 0.015385f, 0.017037f,
			0.018772f, 0.02059f, 0.02249f, 0.024472f, 0.026535f, 0.028679f, 0.030904f, 0.03321f, 0.035595f, 0.03806f,
			0.040604f, 0.043227f, 0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f,
			0.070297f, 0.07368f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f, 0.099373f, 0.103323f,
			0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.12408f, 0.128428f, 0.132839f, 0.137313f, 0.141849f, 0.146447f,
			0.151105f, 0.155823f, 0.1606f, 0.165435f, 0.170327f, 0.175276f, 0.18028f, 0.18534f, 0.190453f, 0.195619f,
			0.200838f, 0.206107f, 0.211427f, 0.216797f, 0.222215f, 0.22768f, 0.233193f, 0.238751f, 0.244353f, 0.25f,
			0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.29067f, 0.296632f, 0.302628f, 0.308658f,
			0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.33928f, 0.345492f, 0.351729f, 0.357992f, 0.36428f, 0.37059f,
			0.376923f, 0.383277f, 0.389651f, 0.396044f, 0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f,
			0.441231f, 0.447736f, 0.454249f, 0.46077f, 0.467298f, 0.473832f, 0.48037f, 0.486912f, 0.493455f, 0.5f,
			0.506545f, 0.513088f, 0.51963f, 0.526168f, 0.532702f, 0.53923f, 0.545751f, 0.552264f, 0.558769f, 0.565263f,
			0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f, 0.610349f, 0.616723f, 0.623077f, 0.62941f,
			0.63572f, 0.642008f, 0.648271f, 0.654508f, 0.66072f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f,
			0.697372f, 0.703368f, 0.70933f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.75f,
			0.755647f, 0.761249f, 0.766807f, 0.77232f, 0.777785f, 0.783203f, 0.788573f, 0.793893f, 0.799162f, 0.804381f,
			0.809547f, 0.81466f, 0.81972f, 0.824724f, 0.829673f, 0.834565f, 0.8394f, 0.844177f, 0.848895f, 0.853553f,
			0.858151f, 0.862687f, 0.867161f, 0.871572f, 0.87592f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f,
			0.900627f, 0.904508f, 0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.92632f, 0.929703f, 0.933013f,
			0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f, 0.959396f, 0.96194f,
			0.964405f, 0.96679f, 0.969096f, 0.971321f, 0.973465f, 0.975528f, 0.97751f, 0.97941f, 0.981228f, 0.982963f,
			0.984615f, 0.986185f, 0.987671f, 0.989074f, 0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f,
			0.996534f, 0.997261f, 0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1f
		};

		internal static readonly int[] tbands = new int[19]
		{
			2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
			28, 32, 40, 48, 56, 68, 80, 96, 120
		};

		internal static readonly int[] extra_bands = new int[22]
		{
			1, 2, 4, 6, 8, 10, 12, 14, 16, 20,
			24, 28, 32, 40, 48, 56, 68, 80, 96, 120,
			160, 200
		};

		internal static readonly float[] weights = new float[422]
		{
			-0.0941125f,
			-0.302976f,
			-0.603555f,
			-0.19393f,
			-0.185983f,
			-0.601617f,
			-0.0465317f,
			-0.114563f,
			-0.103599f,
			-0.618938f,
			-0.317859f,
			-0.169949f,
			-0.0702885f,
			0.148065f,
			0.409524f,
			0.548432f,
			0.367649f,
			-0.494393f,
			0.764306f,
			-1.83957f,
			0.170849f,
			12.786f,
			-1.08848f,
			-1.27284f,
			-16.2606f,
			24.1773f,
			-5.57454f,
			-0.17276f,
			-0.163388f,
			-0.224421f,
			-0.0948944f,
			-0.0728695f,
			-0.26557f,
			-0.100283f,
			-0.0515459f,
			-0.146142f,
			-0.120674f,
			-0.180655f,
			0.12857f,
			0.442138f,
			-0.493735f,
			0.167767f,
			0.206699f,
			-0.197567f,
			0.417999f,
			1.50364f,
			-0.773341f,
			-10.0401f,
			0.401872f,
			2.97966f,
			15.2165f,
			-1.88905f,
			-1.19254f,
			0.0285397f,
			-0.00405139f,
			0.0707565f,
			0.00825699f,
			-0.0927269f,
			-0.010393f,
			-0.00428882f,
			-0.00489743f,
			-0.0709731f,
			-0.00255992f,
			0.0395619f,
			0.226424f,
			0.0325231f,
			0.162175f,
			-0.100118f,
			0.485789f,
			0.12697f,
			0.285937f,
			0.0155637f,
			0.10546f,
			3.05558f,
			1.15059f,
			-1.00904f,
			-1.83088f,
			3.31766f,
			-3.42516f,
			-0.119135f,
			-0.0405654f,
			0.00690068f,
			0.0179877f,
			-0.0382487f,
			0.00597941f,
			-0.0183611f,
			0.00190395f,
			-0.144322f,
			-0.0435671f,
			0.000990594f,
			0.221087f,
			0.142405f,
			0.484066f,
			0.404395f,
			0.511955f,
			-0.237255f,
			0.241742f,
			0.35045f,
			-0.699428f,
			10.3993f,
			2.6507f,
			-2.43459f,
			-4.18838f,
			1.05928f,
			1.71067f,
			0.00667811f,
			-0.0721335f,
			-0.0397346f,
			0.0362704f,
			-0.11496f,
			-0.0235776f,
			0.0082161f,
			-0.0141741f,
			-0.0329699f,
			-0.0354253f,
			0.00277404f,
			-0.290654f,
			-1.14767f,
			-0.319157f,
			-0.686544f,
			0.36897f,
			0.478899f,
			0.182579f,
			-0.411069f,
			0.881104f,
			-4.60683f,
			1.4697f,
			325f / (356f * MathF.E),
			-1.81905f,
			-30.1699f,
			5.55225f,
			0.0019508f,
			-0.123576f,
			-0.0727332f,
			-0.0641597f,
			-0.0534458f,
			-0.108166f,
			-0.0937368f,
			-0.0697883f,
			-0.0275475f,
			-0.192309f,
			-0.110074f,
			0.285375f,
			-0.405597f,
			0.0926724f,
			-0.287881f,
			-0.851193f,
			-0.099493f,
			-0.233764f,
			-1.2852f,
			1.13611f,
			3.12168f,
			-0.0699f,
			-1.86216f,
			2.65292f,
			-7.31036f,
			2.44776f,
			-0.00111802f,
			-0.0632786f,
			-0.0376296f,
			-0.149851f,
			0.142963f,
			0.184368f,
			0.123433f,
			0.0756158f,
			0.117312f,
			0.0933395f,
			0.0692163f,
			0.0842592f,
			0.0704683f,
			0.0589963f,
			0.0942205f,
			-0.448862f,
			0.0262677f,
			0.270352f,
			-0.262317f,
			0.172586f,
			2.00227f,
			-0.159216f,
			0.038422f,
			10.2073f,
			4.15536f,
			-2.3407f,
			-0.0550265f,
			0.00964792f,
			-0.141336f,
			0.0274501f,
			0.0343921f,
			-0.0487428f,
			0.0950172f,
			-0.00775017f,
			-0.0372492f,
			-0.00548121f,
			-0.0663695f,
			0.0960506f,
			-0.200008f,
			-0.0412827f,
			0.58728f,
			0.0515787f,
			0.337254f,
			0.855024f,
			0.668371f,
			-0.114904f,
			-3.62962f,
			-0.467477f,
			-0.215472f,
			2.61537f,
			0.406117f,
			-1.36373f,
			0.0425394f,
			0.12208f,
			0.0934502f,
			0.123055f,
			0.0340935f,
			-0.142466f,
			0.035037f,
			-0.0490666f,
			0.0733208f,
			0.0576672f,
			0.123984f,
			-0.0517194f,
			-0.253018f,
			0.590565f,
			0.145849f,
			0.315185f,
			0.221534f,
			-0.149081f,
			0.216161f,
			-0.349575f,
			24.5664f,
			-0.994196f,
			0.614289f,
			-18.7905f,
			-2.83277f,
			-0.716801f,
			-0.347201f,
			0.479515f,
			-0.246027f,
			0.0758683f,
			0.137293f,
			-0.17781f,
			0.118751f,
			-0.00108329f,
			-0.237334f,
			0.355732f,
			-0.12991f,
			-0.0547627f,
			-0.318576f,
			-0.325524f,
			0.180494f,
			-0.0625604f,
			0.141219f,
			0.344064f,
			0.37658f,
			-0.591772f,
			5.8427f,
			-0.38075f,
			0.221894f,
			-1.41934f,
			-1879430f,
			1.34114f,
			0.0283355f,
			-0.0447856f,
			-0.0211466f,
			-0.0256927f,
			0.0139618f,
			0.0207934f,
			-0.0107666f,
			0.0110969f,
			0.0586069f,
			-0.0253545f,
			-0.0328433f,
			0.11872f,
			-0.216943f,
			0.145748f,
			0.119808f,
			-0.0915211f,
			-0.120647f,
			-0.0787719f,
			-0.143644f,
			-0.595116f,
			-1.152f,
			-1.25335f,
			-1.17092f,
			4.34023f,
			-975268f,
			-1.37033f,
			-0.0401123f,
			0.210602f,
			-0.136656f,
			0.135962f,
			-0.0523293f,
			0.0444604f,
			0.0143928f,
			0.00412666f,
			-0.0193003f,
			0.218452f,
			-0.110204f,
			-2.02563f,
			0.918238f,
			-2.45362f,
			1.19542f,
			-0.061362f,
			-1.92243f,
			0.308111f,
			0.49764f,
			0.912356f,
			0.209272f,
			-2.34525f,
			2.19326f,
			-6.47121f,
			1.69771f,
			-0.725123f,
			0.0118929f,
			0.0377944f,
			0.0554003f,
			0.0226452f,
			-0.0704421f,
			-0.0300309f,
			0.0122978f,
			-0.0041782f,
			-0.0686612f,
			0.0313115f,
			0.039111f,
			0.364111f,
			-0.0945548f,
			0.0229876f,
			-0.17414f,
			0.329795f,
			0.114714f,
			0.30022f,
			0.106997f,
			0.132355f,
			5.79932f,
			0.908058f,
			-0.905324f,
			-3.3561f,
			0.190647f,
			0.184211f,
			-0.673648f,
			0.231807f,
			-0.0586222f,
			0.230752f,
			-0.438277f,
			0.245857f,
			-0.17215f,
			0.0876383f,
			-0.720512f,
			0.162515f,
			0.0170571f,
			0.101781f,
			0.388477f,
			1.32931f,
			1.08548f,
			-0.936301f,
			-2.36958f,
			-6.71988f,
			-3.44376f,
			2.13818f,
			14.2318f,
			4.91459f,
			-3.09052f,
			-9.69191f,
			-0.768234f,
			1.79604f,
			0.0549653f,
			0.163399f,
			0.0797025f,
			0.0343933f,
			-0.0555876f,
			-0.00505673f,
			0.0187258f,
			0.0326628f,
			0.0231486f,
			0.15573f,
			0.0476223f,
			-0.254824f,
			1.60155f,
			-0.801221f,
			2.55496f,
			0.737629f,
			-1.36249f,
			-0.695463f,
			-2.44301f,
			-1.73188f,
			3.95279f,
			1.89068f,
			0.486087f,
			-11.3343f,
			3941600f,
			-0.381439f,
			0.12115f,
			-0.906927f,
			2.93878f,
			1.6388f,
			0.882811f,
			0.874344f,
			1.21726f,
			-0.874545f,
			0.321706f,
			0.785055f,
			0.946558f,
			-0.575066f,
			-3.46553f,
			0.884905f,
			0.0924047f,
			-9.90712f,
			0.391338f,
			0.160103f,
			-2.04954f,
			4.1455f,
			0.0684029f,
			-0.144761f,
			-0.285282f,
			0.379244f,
			-1.1584f,
			-0.0277241f,
			-9.85f,
			-4.82386f,
			3.71333f,
			3.87308f,
			3.52558f
		};

		internal static readonly int[] topo = new int[3] { 25, 15, 2 };

		internal static readonly MLP net = new MLP
		{
			layers = 3,
			topo = topo,
			weights = weights
		};

		internal static readonly float[] tansig_table = new float[201]
		{
			0f, 0.039979f, 0.07983f, 0.119427f, 0.158649f, 0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f,
			0.379949f, 0.413644f, 0.446244f, 0.4777f, 0.507977f, 0.53705f, 0.5649f, 0.591519f, 0.616909f, 0.641077f,
			0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f, 0.761594f, 0.777888f, 0.793199f, 0.807569f, 0.82104f,
			0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f, 0.885352f, 0.893698f, 0.901468f, 0.908698f, 0.91542f,
			0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f, 0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.96109f,
			0.964028f, 0.966747f, 0.969265f, 0.971594f, 0.973749f, 0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f,
			0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f, 0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.99202f,
			0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f, 0.995055f, 0.995434f, 0.995784f, 0.996108f, 0.996407f,
			0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.99759f, 0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f,
			0.998508f, 0.998623f, 0.998728f, 0.998826f, 0.998916f, 0.999f, 0.999076f, 0.999147f, 0.999213f, 0.999273f,
			0.999329f, 0.999381f, 0.999428f, 0.999472f, 0.999513f, 0.99955f, 0.999585f, 0.999617f, 0.999646f, 0.999673f,
			0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f, 0.999798f, 0.999813f, 0.999828f, 0.999841f, 0.999853f,
			0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f, 0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f,
			0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f, 0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.99997f,
			0.999973f, 0.999975f, 0.999977f, 0.999978f, 0.99998f, 0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f,
			0.999988f, 0.999989f, 0.99999f, 0.99999f, 0.999991f, 0.999992f, 0.999992f, 0.999993f, 0.999994f, 0.999994f,
			0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f, 0.999996f, 0.999997f, 0.999997f, 0.999997f, 0.999997f,
			0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f,
			0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f,
			1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f,
			1f
		};

		internal static readonly int[] mono_voice_bandwidth_thresholds = new int[8] { 11000, 1000, 14000, 1000, 17000, 1000, 21000, 2000 };

		internal static readonly int[] mono_music_bandwidth_thresholds = new int[8] { 12000, 1000, 15000, 1000, 18000, 2000, 22000, 2000 };

		internal static readonly int[] stereo_voice_bandwidth_thresholds = new int[8] { 11000, 1000, 14000, 1000, 21000, 2000, 28000, 2000 };

		internal static readonly int[] stereo_music_bandwidth_thresholds = new int[8] { 12000, 1000, 18000, 2000, 21000, 2000, 30000, 2000 };

		internal const int stereo_voice_threshold = 30000;

		internal const int stereo_music_threshold = 30000;

		internal static readonly int[][] mode_thresholds = new int[2][]
		{
			new int[2] { 64000, 16000 },
			new int[2] { 36000, 16000 }
		};
	}
	public static class ResamplerFactory
	{
		public static IResampler CreateResampler(int numChannels, int inRate, int outRate, int quality, TextWriter logger = null)
		{
			return CreateResampler(numChannels, inRate, outRate, inRate, outRate, quality, logger);
		}

		public static IResampler CreateResampler(int numChannels, int ratioNum, int ratioDen, int inRate, int outRate, int quality, TextWriter logger = null)
		{
			if (numChannels <= 0)
			{
				throw new ArgumentOutOfRangeException("numChannels");
			}
			if (ratioNum <= 0)
			{
				throw new ArgumentOutOfRangeException("ratioNum");
			}
			if (ratioDen <= 0)
			{
				throw new ArgumentOutOfRangeException("ratioDen");
			}
			if (inRate <= 0)
			{
				throw new ArgumentOutOfRangeException("inRate");
			}
			if (outRate <= 0)
			{
				throw new ArgumentOutOfRangeException("outRate");
			}
			if (quality < 0 || quality > 10)
			{
				throw new ArgumentOutOfRangeException("quality", "Quality must be between 0 and 10");
			}
			return new SpeexResampler(numChannels, ratioNum, ratioDen, inRate, outRate, quality);
		}
	}
}
namespace Concentus.Silk
{
	internal static class ApplySineWindow
	{
		private static readonly short[] freq_table_Q16 = new short[27]
		{
			12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, 3885,
			3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, 2313, 2214,
			2123, 2038, 1961, 1889, 1822, 1760, 1702
		};

		internal static void silk_apply_sine_window(short[] px_win, int px_win_ptr, short[] px, int px_ptr, int win_type, int length)
		{
			int num = (length >> 2) - 4;
			int num2 = freq_table_Q16[num];
			int num3 = Inlines.silk_SMULWB(num2, -num2);
			int num4;
			int num5;
			if (win_type == 1)
			{
				num4 = 0;
				num5 = num2 + Inlines.silk_RSHIFT(length, 3);
			}
			else
			{
				num4 = 65536;
				num5 = 65536 + Inlines.silk_RSHIFT(num3, 1) + Inlines.silk_RSHIFT(length, 4);
			}
			for (num = 0; num < length; num += 4)
			{
				int num6 = px_win_ptr + num;
				int num7 = px_ptr + num;
				px_win[num6] = (short)Inlines.silk_SMULWB(Inlines.silk_RSHIFT(num4 + num5, 1), px[num7]);
				px_win[num6 + 1] = (short)Inlines.silk_SMULWB(num5, px[num7 + 1]);
				num4 = Inlines.silk_SMULWB(num5, num3) + Inlines.silk_LSHIFT(num5, 1) - num4 + 1;
				num4 = Inlines.silk_min(num4, 65536);
				px_win[num6 + 2] = (short)Inlines.silk_SMULWB(Inlines.silk_RSHIFT(num4 + num5, 1), px[num7 + 2]);
				px_win[num6 + 3] = (short)Inlines.silk_SMULWB(num4, px[num7 + 3]);
				num5 = Inlines.silk_SMULWB(num4, num3) + Inlines.silk_LSHIFT(num4, 1) - num5;
				num5 = Inlines.silk_min(num5, 65536);
			}
		}
	}
	internal static class BurgModified
	{
		private const int MAX_FRAME_SIZE = 384;

		private const int QA = 25;

		private const int N_BITS_HEAD_ROOM = 2;

		private const int MIN_RSHIFTS = -16;

		private const int MAX_RSHIFTS = 7;

		internal static void silk_burg_modified(BoxedValueInt res_nrg, BoxedValueInt res_nrg_Q, int[] A_Q16, short[] x, int x_ptr, int minInvGain_Q30, int subfr_length, int nb_subfr, int D)
		{
			int[] array = new int[16];
			int[] array2 = new int[16];
			int[] array3 = new int[16];
			int[] array4 = new int[17];
			int[] array5 = new int[17];
			int[] array6 = new int[16];
			long num = Inlines.silk_inner_prod16_aligned_64(x, x_ptr, x, x_ptr, subfr_length * nb_subfr);
			int num2 = Inlines.silk_CLZ64(num);
			int num3 = 35 - num2;
			if (num3 > 7)
			{
				num3 = 7;
			}
			if (num3 < -16)
			{
				num3 = -16;
			}
			int num4 = (int)((num3 <= 0) ? Inlines.silk_LSHIFT32((int)num, -num3) : Inlines.silk_RSHIFT64(num, num3));
			array5[0] = (array4[0] = num4 + Inlines.silk_SMMUL(42950, num4) + 1);
			Arrays.MemSetInt(array, 0, 16);
			if (num3 > 0)
			{
				for (int i = 0; i < nb_subfr; i++)
				{
					int num5 = x_ptr + i * subfr_length;
					for (int j = 1; j < D + 1; j++)
					{
						array[j - 1] += (int)Inlines.silk_RSHIFT64(Inlines.silk_inner_prod16_aligned_64(x, num5, x, num5 + j, subfr_length - j), num3);
					}
				}
			}
			else
			{
				for (int i = 0; i < nb_subfr; i++)
				{
					int num5 = x_ptr + i * subfr_length;
					CeltPitchXCorr.pitch_xcorr(x, num5, x, num5 + 1, array6, subfr_length - D, D);
					for (int j = 1; j < D + 1; j++)
					{
						int k = j + subfr_length - D;
						int num6 = 0;
						for (; k < subfr_length; k++)
						{
							num6 = Inlines.MAC16_16(num6, x[num5 + k], x[num5 + k - j]);
						}
						array6[j - 1] += num6;
					}
					for (int j = 1; j < D + 1; j++)
					{
						array[j - 1] += Inlines.silk_LSHIFT32(array6[j - 1], -num3);
					}
				}
			}
			Arrays.MemCopy(array, 0, array2, 0, 16);
			array5[0] = (array4[0] = num4 + Inlines.silk_SMMUL(42950, num4) + 1);
			int num7 = 1073741824;
			int num8 = 0;
			for (int j = 0; j < D; j++)
			{
				int num9;
				int num10;
				if (num3 > -2)
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						int b = -Inlines.silk_LSHIFT32(x[num5 + j], 16 - num3);
						int b2 = -Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], 16 - num3);
						num9 = Inlines.silk_LSHIFT32(x[num5 + j], 9);
						num10 = Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], 9);
						for (int l = 0; l < j; l++)
						{
							array[l] = Inlines.silk_SMLAWB(array[l], b, x[num5 + j - l - 1]);
							array2[l] = Inlines.silk_SMLAWB(array2[l], b2, x[num5 + subfr_length - j + l]);
							int b3 = array3[l];
							num9 = Inlines.silk_SMLAWB(num9, b3, x[num5 + j - l - 1]);
							num10 = Inlines.silk_SMLAWB(num10, b3, x[num5 + subfr_length - j + l]);
						}
						num9 = Inlines.silk_LSHIFT32(-num9, 7 - num3);
						num10 = Inlines.silk_LSHIFT32(-num10, 7 - num3);
						for (int l = 0; l <= j; l++)
						{
							array4[l] = Inlines.silk_SMLAWB(array4[l], num9, x[num5 + j - l]);
							array5[l] = Inlines.silk_SMLAWB(array5[l], num10, x[num5 + subfr_length - j + l - 1]);
						}
					}
				}
				else
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						int b = -Inlines.silk_LSHIFT32(x[num5 + j], -num3);
						int b2 = -Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], -num3);
						num9 = Inlines.silk_LSHIFT32(x[num5 + j], 17);
						num10 = Inlines.silk_LSHIFT32(x[num5 + subfr_length - j - 1], 17);
						for (int l = 0; l < j; l++)
						{
							array[l] = Inlines.silk_MLA(array[l], b, x[num5 + j - l - 1]);
							array2[l] = Inlines.silk_MLA(array2[l], b2, x[num5 + subfr_length - j + l]);
							int c = Inlines.silk_RSHIFT_ROUND(array3[l], 8);
							num9 = Inlines.silk_MLA(num9, x[num5 + j - l - 1], c);
							num10 = Inlines.silk_MLA(num10, x[num5 + subfr_length - j + l], c);
						}
						num9 = -num9;
						num10 = -num10;
						for (int l = 0; l <= j; l++)
						{
							array4[l] = Inlines.silk_SMLAWW(array4[l], num9, Inlines.silk_LSHIFT32(x[num5 + j - l], -num3 - 1));
							array5[l] = Inlines.silk_SMLAWW(array5[l], num10, Inlines.silk_LSHIFT32(x[num5 + subfr_length - j + l - 1], -num3 - 1));
						}
					}
				}
				num9 = array[j];
				num10 = array2[j];
				int a = 0;
				int num11 = Inlines.silk_ADD32(array5[0], array4[0]);
				for (int l = 0; l < j; l++)
				{
					int b3 = array3[l];
					num2 = Inlines.silk_CLZ32(Inlines.silk_abs(b3)) - 1;
					num2 = Inlines.silk_min(7, num2);
					int c = Inlines.silk_LSHIFT32(b3, num2);
					num9 = Inlines.silk_ADD_LSHIFT32(num9, Inlines.silk_SMMUL(array2[j - l - 1], c), 7 - num2);
					num10 = Inlines.silk_ADD_LSHIFT32(num10, Inlines.silk_SMMUL(array[j - l - 1], c), 7 - num2);
					a = Inlines.silk_ADD_LSHIFT32(a, Inlines.silk_SMMUL(array5[j - l], c), 7 - num2);
					num11 = Inlines.silk_ADD_LSHIFT32(num11, Inlines.silk_SMMUL(Inlines.silk_ADD32(array5[l + 1], array4[l + 1]), c), 7 - num2);
				}
				array4[j + 1] = num9;
				array5[j + 1] = num10;
				a = Inlines.silk_ADD32(a, num10);
				a = Inlines.silk_LSHIFT32(-a, 1);
				int num12 = ((Inlines.silk_abs(a) >= num11) ? ((a > 0) ? int.MaxValue : int.MinValue) : Inlines.silk_DIV32_varQ(a, num11, 31));
				num9 = 1073741824 - Inlines.silk_SMMUL(num12, num12);
				num9 = Inlines.silk_LSHIFT(Inlines.silk_SMMUL(num7, num9), 2);
				if (num9 <= minInvGain_Q30)
				{
					num10 = 1073741824 - Inlines.silk_DIV32_varQ(minInvGain_Q30, num7, 30);
					num12 = Inlines.silk_SQRT_APPROX(num10);
					num12 = Inlines.silk_RSHIFT32(num12 + Inlines.silk_DIV32(num10, num12), 1);
					num12 = Inlines.silk_LSHIFT32(num12, 16);
					if (a < 0)
					{
						num12 = -num12;
					}
					num7 = minInvGain_Q30;
					num8 = 1;
				}
				else
				{
					num7 = num9;
				}
				for (int l = 0; l < j + 1 >> 1; l++)
				{
					num9 = array3[l];
					num10 = array3[j - l - 1];
					array3[l] = Inlines.silk_ADD_LSHIFT32(num9, Inlines.silk_SMMUL(num10, num12), 1);
					array3[j - l - 1] = Inlines.silk_ADD_LSHIFT32(num10, Inlines.silk_SMMUL(num9, num12), 1);
				}
				array3[j] = Inlines.silk_RSHIFT32(num12, 6);
				if (num8 != 0)
				{
					for (int l = j + 1; l < D; l++)
					{
						array3[l] = 0;
					}
					break;
				}
				for (int l = 0; l <= j + 1; l++)
				{
					num9 = array4[l];
					num10 = array5[j - l + 1];
					array4[l] = Inlines.silk_ADD_LSHIFT32(num9, Inlines.silk_SMMUL(num10, num12), 1);
					array5[j - l + 1] = Inlines.silk_ADD_LSHIFT32(num10, Inlines.silk_SMMUL(num9, num12), 1);
				}
			}
			if (num8 != 0)
			{
				for (int l = 0; l < D; l++)
				{
					A_Q16[l] = -Inlines.silk_RSHIFT_ROUND(array3[l], 9);
				}
				if (num3 > 0)
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						num4 -= (int)Inlines.silk_RSHIFT64(Inlines.silk_inner_prod16_aligned_64(x, num5, x, num5, D), num3);
					}
				}
				else
				{
					for (int i = 0; i < nb_subfr; i++)
					{
						int num5 = x_ptr + i * subfr_length;
						num4 -= Inlines.silk_LSHIFT32(Inlines.silk_inner_prod_self(x, num5, D), -num3);
					}
				}
				res_nrg.Val = Inlines.silk_LSHIFT(Inlines.silk_SMMUL(num7, num4), 2);
				res_nrg_Q.Val = -num3;
			}
			else
			{
				int num11 = array4[0];
				int num9 = 65536;
				for (int l = 0; l < D; l++)
				{
					int c = Inlines.silk_RSHIFT_ROUND(array3[l], 9);
					num11 = Inlines.silk_SMLAWW(num11, array4[l + 1], c);
					num9 = Inlines.silk_SMLAWW(num9, c, c);
					A_Q16[l] = -c;
				}
				res_nrg.Val = Inlines.silk_SMLAWW(num11, Inlines.silk_SMMUL(42950, num4), -num9);
				res_nrg_Q.Val = -num3;
			}
		}
	}
	internal static class BWExpander
	{
		internal static void silk_bwexpander_32(int[] ar, int d, int chirp_Q16)
		{
			int b = chirp_Q16 - 65536;
			for (int i = 0; i < d - 1; i++)
			{
				ar[i] = Inlines.silk_SMULWW(chirp_Q16, ar[i]);
				chirp_Q16 += Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, b), 16);
			}
			ar[d - 1] = Inlines.silk_SMULWW(chirp_Q16, ar[d - 1]);
		}

		internal static void silk_bwexpander(short[] ar, int d, int chirp_Q16)
		{
			int b = chirp_Q16 - 65536;
			for (int i = 0; i < d - 1; i++)
			{
				ar[i] = (short)Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, ar[i]), 16);
				chirp_Q16 += Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, b), 16);
			}
			ar[d - 1] = (short)Inlines.silk_RSHIFT_ROUND(Inlines.silk_MUL(chirp_Q16, ar[d - 1]), 16);
		}
	}
	internal static class CNG
	{
		internal static void silk_CNG_exc(Span<int> exc_Q10, int exc_Q10_ptr, int[] exc_buf_Q14, int Gain_Q16, int length, ref int rand_seed)
		{
			int num;
			for (num = 255; num > length; num = Inlines.silk_RSHIFT(num, 1))
			{
			}
			int num2 = rand_seed;
			for (int i = exc_Q10_ptr; i < exc_Q10_ptr + length; i++)
			{
				num2 = Inlines.silk_RAND(num2);
				int num3 = Inlines.silk_RSHIFT(num2, 24) & num;
				exc_Q10[i] = (short)Inlines.silk_SAT16(Inlines.silk_SMULWW(exc_buf_Q14[num3], Gain_Q16 >> 4));
			}
			rand_seed = num2;
		}

		internal static void silk_CNG_Reset(SilkChannelDecoder psDec)
		{
			int num = Inlines.silk_DIV32_16(32767, (short)(psDec.LPC_order + 1));
			int num2 = 0;
			for (int i = 0; i < psDec.LPC_order; i++)
			{
				num2 += num;
				psDec.sCNG.CNG_smth_NLSF_Q15[i] = (short)num2;
			}
			psDec.sCNG.CNG_smth_Gain_Q16 = 0;
			psDec.sCNG.rand_seed = 3176576;
		}

		internal static void silk_CNG(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, Span<short> frame, int frame_ptr, int length)
		{
			short[] array = new short[psDec.LPC_order];
			CNGState sCNG = psDec.sCNG;
			if (psDec.fs_kHz != sCNG.fs_kHz)
			{
				silk_CNG_Reset(psDec);
				sCNG.fs_kHz = psDec.fs_kHz;
			}
			if (psDec.lossCnt == 0 && psDec.prevSignalType == 0)
			{
				for (int i = 0; i < psDec.LPC_order; i++)
				{
					sCNG.CNG_smth_NLSF_Q15[i] += (short)Inlines.silk_SMULWB(psDec.prevNLSF_Q15[i] - sCNG.CNG_smth_NLSF_Q15[i], 16348);
				}
				int num = 0;
				for (int i = 0; i < psDec.nb_subfr; i++)
				{
					if (psDecCtrl.Gains_Q16[i] > num)
					{
						num = psDecCtrl.Gains_Q16[i];
					}
				}
				Arrays.MemMoveInt(sCNG.CNG_exc_buf_Q14, 0, psDec.subfr_length, (psDec.nb_subfr - 1) * psDec.subfr_length);
				for (int i = 0; i < psDec.nb_subfr; i++)
				{
					sCNG.CNG_smth_Gain_Q16 += Inlines.silk_SMULWB(psDecCtrl.Gains_Q16[i] - sCNG.CNG_smth_Gain_Q16, 4634);
				}
			}
			if (psDec.lossCnt != 0)
			{
				int[] array2 = new int[length + 16];
				int num2 = Inlines.silk_SMULWW(psDec.sPLC.randScale_Q14, psDec.sPLC.prevGain_Q16[1]);
				if (num2 >= 2097152 || sCNG.CNG_smth_Gain_Q16 > 8388608)
				{
					num2 = Inlines.silk_SMULTT(num2, num2);
					num2 = Inlines.silk_SUB_LSHIFT32(Inlines.silk_SMULTT(sCNG.CNG_smth_Gain_Q16, sCNG.CNG_smth_Gain_Q16), num2, 5);
					num2 = Inlines.silk_LSHIFT32(Inlines.silk_SQRT_APPROX(num2), 16);
				}
				else
				{
					num2 = Inlines.silk_SMULWW(num2, num2);
					num2 = Inlines.silk_SUB_LSHIFT32(Inlines.silk_SMULWW(sCNG.CNG_smth_Gain_Q16, sCNG.CNG_smth_Gain_Q16), num2, 5);
					num2 = Inlines.silk_LSHIFT32(Inlines.silk_SQRT_APPROX(num2), 8);
				}
				silk_CNG_exc(array2, 16, sCNG.CNG_exc_buf_Q14, num2, length, ref sCNG.rand_seed);
				NLSF.silk_NLSF2A(array, sCNG.CNG_smth_NLSF_Q15, psDec.LPC_order);
				Arrays.MemCopy(sCNG.CNG_synth_state, 0, array2, 0, 16);
				for (int i = 0; i < length; i++)
				{
					int num3 = 16 + i;
					int a = Inlines.silk_RSHIFT(psDec.LPC_order, 1);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 1], array[0]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 2], array[1]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 3], array[2]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 4], array[3]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 5], array[4]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 6], array[5]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 7], array[6]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 8], array[7]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 9], array[8]);
					a = Inlines.silk_SMLAWB(a, array2[num3 - 10], array[9]);
					if (psDec.LPC_order == 16)
					{
						a = Inlines.silk_SMLAWB(a, array2[num3 - 11], array[10]);
						a = Inlines.silk_SMLAWB(a, array2[num3 - 12], array[11]);
						a = Inlines.silk_SMLAWB(a, array2[num3 - 13], array[12]);
						a = Inlines.silk_SMLAWB(a, array2[num3 - 14], array[13]);
						a = Inlines.silk_SMLAWB(a, array2[num3 - 15], array[14]);
						a = Inlines.silk_SMLAWB(a, array2[num3 - 16], array[15]);
					}
					array2[num3] = Inlines.silk_ADD_LSHIFT(array2[num3], a, 4);
					frame[frame_ptr + i] = Inlines.silk_ADD_SAT16(frame[frame_ptr + i], (short)Inlines.silk_RSHIFT_ROUND(array2[num3], 10));
				}
				Arrays.MemCopy(array2, length, sCNG.CNG_synth_state, 0, 16);
			}
			else
			{
				Arrays.MemSetInt(sCNG.CNG_synth_state, 0, psDec.LPC_order);
			}
		}
	}
	internal static class CodeSigns
	{
		private static int silk_enc_map(int a)
		{
			return Inlines.silk_RSHIFT(a, 15) + 1;
		}

		private static int silk_dec_map(int a)
		{
			return Inlines.silk_LSHIFT(a, 1) - 1;
		}

		internal static void silk_encode_signs(EntropyCoder psRangeEnc, Span<byte> encodedData, Span<sbyte> pulses, int length, int signalType, int quantOffsetType, int[] sum_pulses)
		{
			byte[] array = new byte[2];
			byte[] silk_sign_iCDF = Tables.silk_sign_iCDF;
			array[1] = 0;
			int num = 0;
			int num2 = Inlines.silk_SMULBB(7, Inlines.silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
			int num3 = num2;
			length = Inlines.silk_RSHIFT(length + 8, 4);
			for (num2 = 0; num2 < length; num2++)
			{
				int num4 = sum_pulses[num2];
				if (num4 > 0)
				{
					array[0] = silk_sign_iCDF[num3 + Inlines.silk_min(num4 & 0x1F, 6)];
					for (int i = num; i < num + 16; i++)
					{
						if (pulses[i] != 0)
						{
							psRangeEnc.enc_icdf(encodedData, silk_enc_map(pulses[i]), array, 8u);
						}
					}
				}
				num += 16;
			}
		}

		internal static void silk_decode_signs(EntropyCoder psRangeDec, ReadOnlySpan<byte> encodedData, short[] pulses, int length, int signalType, int quantOffsetType, int[] sum_pulses)
		{
			byte[] array = new byte[2];
			byte[] silk_sign_iCDF = Tables.silk_sign_iCDF;
			array[1] = 0;
			int num = 0;
			int num2 = Inlines.silk_SMULBB(7, Inlines.silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
			int num3 = num2;
			length = Inlines.silk_RSHIFT(length + 8, 4);
			for (num2 = 0; num2 < length; num2++)
			{
				int num4 = sum_pulses[num2];
				if (num4 > 0)
				{
					array[0] = silk_sign_iCDF[num3 + Inlines.silk_min(num4 & 0x1F, 6)];
					for (int i = 0; i < 16; i++)
					{
						if (pulses[num + i] > 0)
						{
							pulses[num + i] *= (short)silk_dec_map(psRangeDec.dec_icdf(encodedData, array, 8u));
						}
					}
				}
				num += 16;
			}
		}
	}
	internal static class CorrelateMatrix
	{
		internal static void silk_corrVector(short[] x, int x_ptr, short[] t, int t_ptr, int L, int order, int[] Xt, int rshifts)
		{
			int num = x_ptr + order - 1;
			if (rshifts > 0)
			{
				for (int i = 0; i < order; i++)
				{
					int num2 = 0;
					for (int j = 0; j < L; j++)
					{
						num2 += Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num + j], t[t_ptr + j]), rshifts);
					}
					Xt[i] = num2;
					num--;
				}
			}
			else
			{
				for (int i = 0; i < order; i++)
				{
					Xt[i] = Inlines.silk_inner_prod(x, num, t, t_ptr, L);
					num--;
				}
			}
		}

		internal static void silk_corrMatrix(short[] x, int x_ptr, int L, int order, int head_room, int[] XX, int XX_ptr, BoxedValueInt rshifts)
		{
			SumSqrShift.silk_sum_sqr_shift(out var energy, out var shift, x, x_ptr, L + order - 1);
			int num = Inlines.silk_max(head_room - Inlines.silk_CLZ32(energy), 0);
			energy = Inlines.silk_RSHIFT32(energy, num);
			shift += num;
			for (int i = x_ptr; i < x_ptr + order - 1; i++)
			{
				energy -= Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[i], x[i]), shift);
			}
			if (shift < rshifts.Val)
			{
				energy = Inlines.silk_RSHIFT32(energy, rshifts.Val - shift);
				shift = rshifts.Val;
			}
			Inlines.MatrixSet(XX, XX_ptr, 0, 0, order, energy);
			int num2 = x_ptr + order - 1;
			for (int j = 1; j < order; j++)
			{
				energy = Inlines.silk_SUB32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 + L - j], x[num2 + L - j]), shift));
				energy = Inlines.silk_ADD32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 - j], x[num2 - j]), shift));
				Inlines.MatrixSet(XX, XX_ptr, j, j, order, energy);
			}
			int num3 = x_ptr + order - 2;
			if (shift > 0)
			{
				for (int k = 1; k < order; k++)
				{
					energy = 0;
					for (int i = 0; i < L; i++)
					{
						energy += Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 + i], x[num3 + i]), shift);
					}
					Inlines.MatrixSet(XX, XX_ptr, k, 0, order, energy);
					Inlines.MatrixSet(XX, XX_ptr, 0, k, order, energy);
					for (int j = 1; j < order - k; j++)
					{
						energy = Inlines.silk_SUB32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 + L - j], x[num3 + L - j]), shift));
						energy = Inlines.silk_ADD32(energy, Inlines.silk_RSHIFT32(Inlines.silk_SMULBB(x[num2 - j], x[num3 - j]), shift));
						Inlines.MatrixSet(XX, XX_ptr, k + j, j, order, energy);
						Inlines.MatrixSet(XX, XX_ptr, j, k + j, order, energy);
					}
					num3--;
				}
			}
			else
			{
				for (int k = 1; k < order; k++)
				{
					energy = Inlines.silk_inner_prod(x, num2, x, num3, L);
					Inlines.MatrixSet(XX, XX_ptr, k, 0, order, energy);
					Inlines.MatrixSet(XX, XX_ptr, 0, k, order, energy);
					for (int j = 1; j < order - k; j++)
					{
						energy = Inlines.silk_SUB32(energy, Inlines.silk_SMULBB(x[num2 + L - j], x[num3 + L - j]));
						energy = Inlines.silk_SMLABB(energy, x[num2 - j], x[num3 - j]);
						Inlines.MatrixSet(XX, XX_ptr, k + j, j, order, energy);
						Inlines.MatrixSet(XX, XX_ptr, j, k + j, order, energy);
					}
					num3--;
				}
			}
			rshifts.Val = shift;
		}
	}
	internal static class DecodeAPI
	{
		internal static int silk_InitDecoder(SilkDecoder decState)
		{
			decState.Reset();
			int result = SilkError.SILK_NO_ERROR;
			SilkChannelDecoder[] channel_state = decState.channel_state;
			for (int i = 0; i < 2; i++)
			{
				result = channel_state[i].silk_init_decoder();
			}
			decState.sStereo.Reset();
			decState.prev_decode_only_middle = 0;
			return result;
		}

		internal static int silk_Decode(SilkDecoder psDec, DecControlState decControl, ReadOnlySpan<byte> frameData, int lostFlag, int newPacketFlag, EntropyCoder psRangeDec, Span<short> samplesOut, int samplesOut_ptr, out int nSamplesOut)
		{
			int num = 0;
			int num2 = SilkError.SILK_NO_ERROR;
			BoxedValueInt boxedValueInt = new BoxedValueInt();
			int[] array = new int[2];
			int[] array2 = new int[2];
			SilkChannelDecoder[] channel_state = psDec.channel_state;
			nSamplesOut = 0;
			if (newPacketFlag != 0)
			{
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					channel_state[i].nFramesDecoded = 0;
				}
			}
			if (decControl.nChannelsInternal > psDec.nChannelsInternal)
			{
				num2 += channel_state[1].silk_init_decoder();
			}
			int num3 = ((decControl.nChannelsInternal == 1 && psDec.nChannelsInternal == 2 && decControl.internalSampleRate == 1000 * channel_state[0].fs_kHz) ? 1 : 0);
			if (channel_state[0].nFramesDecoded == 0)
			{
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					if (decControl.payloadSize_ms == 0)
					{
						channel_state[i].nFramesPerPacket = 1;
						channel_state[i].nb_subfr = 2;
					}
					else if (decControl.payloadSize_ms == 10)
					{
						channel_state[i].nFramesPerPacket = 1;
						channel_state[i].nb_subfr = 2;
					}
					else if (decControl.payloadSize_ms == 20)
					{
						channel_state[i].nFramesPerPacket = 1;
						channel_state[i].nb_subfr = 4;
					}
					else if (decControl.payloadSize_ms == 40)
					{
						channel_state[i].nFramesPerPacket = 2;
						channel_state[i].nb_subfr = 4;
					}
					else
					{
						if (decControl.payloadSize_ms != 60)
						{
							return SilkError.SILK_DEC_INVALID_FRAME_SIZE;
						}
						channel_state[i].nFramesPerPacket = 3;
						channel_state[i].nb_subfr = 4;
					}
					int num4 = (decControl.internalSampleRate >> 10) + 1;
					if (num4 != 8 && num4 != 12 && num4 != 16)
					{
						return SilkError.SILK_DEC_INVALID_SAMPLING_FREQUENCY;
					}
					num2 += channel_state[i].silk_decoder_set_fs(num4, decControl.API_sampleRate);
				}
			}
			if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 2 && (psDec.nChannelsAPI == 1 || psDec.nChannelsInternal == 1))
			{
				Arrays.MemSetShort(psDec.sStereo.pred_prev_Q13, 0, 2);
				Arrays.MemSetShort(psDec.sStereo.sSide, 0, 2);
				channel_state[1].resampler_state.Assign(channel_state[0].resampler_state);
			}
			psDec.nChannelsAPI = decControl.nChannelsAPI;
			psDec.nChannelsInternal = decControl.nChannelsInternal;
			if (decControl.API_sampleRate > 48000 || decControl.API_sampleRate < 8000)
			{
				return SilkError.SILK_DEC_INVALID_SAMPLING_FREQUENCY;
			}
			if (lostFlag != 1 && channel_state[0].nFramesDecoded == 0)
			{
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					for (int j = 0; j < channel_state[i].nFramesPerPacket; j++)
					{
						channel_state[i].VAD_flags[j] = psRangeDec.dec_bit_logp(frameData, 1u);
					}
					channel_state[i].LBRR_flag = psRangeDec.dec_bit_logp(frameData, 1u);
				}
				for (int i = 0; i < decControl.nChannelsInternal; i++)
				{
					Arrays.MemSetInt(channel_state[i].LBRR_flags, 0, 3);
					if (channel_state[i].LBRR_flag == 0)
					{
						continue;
					}
					if (channel_state[i].nFramesPerPacket == 1)
					{
						channel_state[i].LBRR_flags[0] = 1;
						continue;
					}
					int a = psRangeDec.dec_icdf(frameData, Tables.silk_LBRR_flags_iCDF_ptr[channel_state[i].nFramesPerPacket - 2], 8u) + 1;
					for (int j = 0; j < channel_state[i].nFramesPerPacket; j++)
					{
						channel_state[i].LBRR_flags[j] = Inlines.silk_RSHIFT(a, j) & 1;
					}
				}
				if (lostFlag == 0)
				{
					for (int j = 0; j < channel_state[0].nFramesPerPacket; j++)
					{
						for (int i = 0; i < decControl.nChannelsInternal; i++)
						{
							if (channel_state[i].LBRR_flags[j] == 0)
							{
								continue;
							}
							short[] pulses = new short[320];
							if (decControl.nChannelsInternal == 2 && i == 0)
							{
								Stereo.silk_stereo_decode_pred(psRangeDec, frameData, array2);
								if (channel_state[1].LBRR_flags[j] == 0)
								{
									BoxedValueInt boxedValueInt2 = new BoxedValueInt(num);
									Stereo.silk_stereo_decode_mid_only(psRangeDec, frameData, boxedValueInt2);
									num = boxedValueInt2.Val;
								}
							}
							DecodeIndices.silk_decode_indices(condCoding: (j > 0 && channel_state[i].LBRR_flags[j - 1] != 0) ? 2 : 0, psDec: channel_state[i], psRangeDec: psRangeDec, frameData: frameData, FrameIndex: j, decode_LBRR: 1);
							DecodePulses.silk_decode_pulses(psRangeDec, frameData, pulses, channel_state[i].indices.signalType, channel_state[i].indices.quantOffsetType, channel_state[i].frame_length);
						}
					}
				}
			}
			if (decControl.nChannelsInternal == 2)
			{
				if (lostFlag == 0 || (lostFlag == 2 && channel_state[0].LBRR_flags[channel_state[0].nFramesDecoded] == 1))
				{
					Stereo.silk_stereo_decode_pred(psRangeDec, frameData, array2);
					if ((lostFlag == 0 && channel_state[1].VAD_flags[channel_state[0].nFramesDecoded] == 0) || (lostFlag == 2 && channel_state[1].LBRR_flags[channel_state[0].nFramesDecoded] == 0))
					{
						BoxedValueInt boxedValueInt3 = new BoxedValueInt(num);
						Stereo.silk_stereo_decode_mid_only(psRangeDec, frameData, boxedValueInt3);
						num = boxedValueInt3.Val;
					}
					else
					{
						num = 0;
					}
				}
				else
				{
					for (int i = 0; i < 2; i++)
					{
						array2[i] = psDec.sStereo.pred_prev_Q13[i];
					}
				}
			}
			if (decControl.nChannelsInternal == 2 && num == 0 && psDec.prev_decode_only_middle == 1)
			{
				Arrays.MemSetShort(psDec.channel_state[1].outBuf, 0, 480);
				Arrays.MemSetInt(psDec.channel_state[1].sLPC_Q14_buf, 0, 16);
				psDec.channel_state[1].lagPrev = 100;
				psDec.channel_state[1].LastGainIndex = 10;
				psDec.channel_state[1].prevSignalType = 0;
				psDec.channel_state[1].first_frame_after_reset = 1;
			}
			int num5 = ((decControl.internalSampleRate * decControl.nChannelsInternal < decControl.API_sampleRate * decControl.nChannelsAPI) ? 1 : 0);
			Span<short> span;
			if (num5 != 0)
			{
				span = samplesOut;
				array[0] = samplesOut_ptr;
				array[1] = samplesOut_ptr + channel_state[0].frame_length + 2;
			}
			else
			{
				span = new short[decControl.nChannelsInternal * (channel_state[0].frame_length + 2)];
				array[0] = 0;
				array[1] = channel_state[0].frame_length + 2;
			}
			int num6 = ((lostFlag != 0) ? ((psDec.prev_decode_only_middle == 0 || (decControl.nChannelsInternal == 2 && lostFlag == 2 && channel_state[1].LBRR_flags[channel_state[1].nFramesDecoded] == 1)) ? 1 : 0) : ((num == 0) ? 1 : 0));
			for (int i = 0; i < decControl.nChannelsInternal; i++)
			{
				if (i == 0 || num6 != 0)
				{
					int num7 = channel_state[0].nFramesDecoded - i;
					int condCoding2 = ((num7 > 0) ? ((lostFlag == 2) ? ((channel_state[i].LBRR_flags[num7 - 1] != 0) ? 2 : 0) : ((i > 0 && psDec.prev_decode_only_middle != 0) ? 1 : 2)) : 0);
					num2 += channel_state[i].silk_decode_frame(psRangeDec, frameData, span, array[i] + 2, boxedValueInt, lostFlag, condCoding2);
				}
				else
				{
					Arrays.MemSetWithOffset<short>(span, 0, array[i] + 2, boxedValueInt.Val);
				}
				channel_state[i].nFramesDecoded++;
			}
			if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 2)
			{
				Stereo.silk_stereo_MS_to_LR(psDec.sStereo, span, array[0], span, array[1], array2, channel_state[0].fs_kHz, boxedValueInt.Val);
			}
			else
			{
				psDec.sStereo.sMid.AsSpan(0, 2).CopyTo(span.Slice(array[0]));
				span.Slice(array[0] + boxedValueInt.Val, 2).CopyTo(psDec.sStereo.sMid);
			}
			nSamplesOut = Inlines.silk_DIV32(boxedValueInt.Val * decControl.API_sampleRate, Inlines.silk_SMULBB(channel_state[0].fs_kHz, 1000));
			Span<short> output;
			int num8;
			if (decControl.nChannelsAPI == 2)
			{
				output = new short[nSamplesOut];
				num8 = 0;
			}
			else
			{
				output = samplesOut;
				num8 = samplesOut_ptr;
			}
			if (num5 != 0)
			{
				short[] array3 = new short[decControl.nChannelsInternal * (channel_state[0].frame_length + 2)];
				samplesOut.Slice(samplesOut_ptr, decControl.nChannelsInternal * (channel_state[0].frame_length + 2)).CopyTo(array3);
				span = array3;
				array[0] = 0;
				array[1] = channel_state[0].frame_length + 2;
			}
			for (int i = 0; i < Inlines.silk_min(decControl.nChannelsAPI, decControl.nChannelsInternal); i++)
			{
				num2 += Resampler.silk_resampler(channel_state[i].resampler_state, output, num8, span, array[i] + 1, boxedValueInt.Val);
				if (decControl.nChannelsAPI == 2)
				{
					int num9 = samplesOut_ptr + i;
					for (int j = 0; j < nSamplesOut; j++)
					{
						samplesOut[num9 + 2 * j] = output[num8 + j];
					}
				}
			}
			if (decControl.nChannelsAPI == 2 && decControl.nChannelsInternal == 1)
			{
				if (num3 != 0)
				{
					num2 += Resampler.silk_resampler(channel_state[1].resampler_state, output, num8, span, array[0] + 1, boxedValueInt.Val);
					for (int j = 0; j < nSamplesOut; j++)
					{
						samplesOut[samplesOut_ptr + 1 + 2 * j] = output[num8 + j];
					}
				}
				else
				{
					for (int j = 0; j < nSamplesOut; j++)
					{
						samplesOut[samplesOut_ptr + 1 + 2 * j] = samplesOut[samplesOut_ptr + 2 * j];
					}
				}
			}
			if (channel_state[0].prevSignalType == 2)
			{
				int[] array4 = new int[3] { 6, 4, 3 };
				decControl.prevPitchLag = channel_state[0].lagPrev * array4[channel_state[0].fs_kHz - 8 >> 2];
			}
			else
			{
				decControl.prevPitchLag = 0;
			}
			if (lostFlag == 1)
			{
				for (int j = 0; j < psDec.nChannelsInternal; j++)
				{
					psDec.channel_state[j].LastGainIndex = 10;
				}
			}
			else
			{
				psDec.prev_decode_only_middle = num;
			}
			return num2;
		}
	}
	internal static class DecodeCore
	{
		internal static void silk_decode_core(SilkChannelDecoder psDec, SilkDecoderControl psDecCtrl, Span<short> xq, int xq_ptr, short[] pulses)
		{
			int num = 0;
			short[] lTPCoef_Q = psDecCtrl.LTPCoef_Q14;
			short[] array = new short[psDec.ltp_mem_length];
			int[] array2 = new int[psDec.ltp_mem_length + psDec.frame_length];
			int[] array3 = new int[psDec.subfr_length];
			int[] array4 = new int[psDec.subfr_length + 16];
			int num2 = Tables.silk_Quantization_Offsets_Q10[psDec.indices.signalType >> 1][psDec.indices.quantOffsetType];
			int num3 = ((psDec.indices.NLSFInterpCoef_Q2 < 4) ? 1 : 0);
			int seed = psDec.indices.Seed;
			for (int i = 0; i < psDec.frame_length; i++)
			{
				seed = Inlines.silk_RAND(seed);
				psDec.exc_Q14[i] = Inlines.silk_LSHIFT(pulses[i], 14);
				if (psDec.exc_Q14[i] > 0)
				{
					psDec.exc_Q14[i] -= 1280;
				}
				else if (psDec.exc_Q14[i] < 0)
				{
					psDec.exc_Q14[i] += 1280;
				}
				psDec.exc_Q14[i] += num2 << 4;
				if (seed < 0)
				{
					psDec.exc_Q14[i] = -psDec.exc_Q14[i];
				}
				seed = Inlines.silk_ADD32_ovflw(seed, pulses[i]);
			}
			Arrays.MemCopy(psDec.sLPC_Q14_buf, 0, array4, 0, 16);
			int num4 = 0;
			int num5 = xq_ptr;
			int num6 = psDec.ltp_mem_length;
			for (int j = 0; j < psDec.nb_subfr; j++)
			{
				int[] array5 = array3;
				int num7 = 0;
				short[] array6 = psDecCtrl.PredCoef_Q12[j >> 1];
				int num8 = j * 5;
				int num9 = psDec.indices.signalType;
				int b = Inlines.silk_RSHIFT(psDecCtrl.Gains_Q16[j], 6);
				int a = Inlines.silk_INVERSE32_varQ(psDecCtrl.Gains_Q16[j], 47);
				int num10;
				if (psDecCtrl.Gains_Q16[j] != psDec.prev_gain_Q16)
				{
					num10 = Inlines.silk_DIV32_varQ(psDec.prev_gain_Q16, psDecCtrl.Gains_Q16[j], 16);
					for (int i = 0; i < 16; i++)
					{
						array4[i] = Inlines.silk_SMULWW(num10, array4[i]);
					}
				}
				else
				{
					num10 = 65536;
				}
				psDec.prev_gain_Q16 = psDecCtrl.Gains_Q16[j];
				if (psDec.lossCnt != 0 && psDec.prevSignalType == 2 && psDec.indices.signalType != 2 && j < 2)
				{
					Arrays.MemSetWithOffset(lTPCoef_Q, (short)0, num8, 5);
					lTPCoef_Q[num8 + 2] = 4096;
					num9 = 2;
					psDecCtrl.pitchL[j] = psDec.lagPrev;
				}
				if (num9 == 2)
				{
					num = psDecCtrl.pitchL[j];
					if (j == 0 || (j == 2 && num3 != 0))
					{
						int num11 = psDec.ltp_mem_length - num - psDec.LPC_order - 2;
						if (j == 2)
						{
							xq.Slice(xq_ptr, 2 * psDec.subfr_length).CopyTo(psDec.outBuf.AsSpan(psDec.ltp_mem_length));
						}
						Filters.silk_LPC_analysis_filter(array, num11, psDec.outBuf, num11 + j * psDec.subfr_length, array6, 0, psDec.ltp_mem_length - num11, psDec.LPC_order);
						if (j == 0)
						{
							a = Inlines.silk_LSHIFT(Inlines.silk_SMULWB(a, psDecCtrl.LTP_scale_Q14), 2);
						}
						for (int i = 0; i < num + 2; i++)
						{
							array2[num6 - i - 1] = Inlines.silk_SMULWB(a, array[psDec.ltp_mem_length - i - 1]);
						}
					}
					else if (num10 != 65536)
					{
						for (int i = 0; i < num + 2; i++)
						{
							array2[num6 - i - 1] = Inlines.silk_SMULWW(num10, array2[num6 - i - 1]);
						}
					}
				}
				if (num9 == 2)
				{
					int num12 = num6 - num + 2;
					for (int i = 0; i < psDec.subfr_length; i++)
					{
						int a2 = 2;
						a2 = Inlines.silk_SMLAWB(a2, array2[num12], lTPCoef_Q[num8]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 1], lTPCoef_Q[num8 + 1]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 2], lTPCoef_Q[num8 + 2]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 3], lTPCoef_Q[num8 + 3]);
						a2 = Inlines.silk_SMLAWB(a2, array2[num12 - 4], lTPCoef_Q[num8 + 4]);
						num12++;
						array5[num7 + i] = Inlines.silk_ADD_LSHIFT32(psDec.exc_Q14[num4 + i], a2, 1);
						array2[num6] = Inlines.silk_LSHIFT(array5[num7 + i], 1);
						num6++;
					}
				}
				else
				{
					array5 = psDec.exc_Q14;
					num7 = num4;
				}
				for (int i = 0; i < psDec.subfr_length; i++)
				{
					int a3 = Inlines.silk_RSHIFT(psDec.LPC_order, 1);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 1], array6[0]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 2], array6[1]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 3], array6[2]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 4], array6[3]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 5], array6[4]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 6], array6[5]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 7], array6[6]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 8], array6[7]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 9], array6[8]);
					a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 10], array6[9]);
					if (psDec.LPC_order == 16)
					{
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 11], array6[10]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 12], array6[11]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 13], array6[12]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 14], array6[13]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 15], array6[14]);
						a3 = Inlines.silk_SMLAWB(a3, array4[16 + i - 16], array6[15]);
					}
					array4[16 + i] = Inlines.silk_ADD_LSHIFT32(array5[num7 + i], a3, 4);
					xq[num5 + i] = (short)Inlines.silk_SAT16(Inlines.silk_RSHIFT_ROUND(Inlines.silk_SMULWW(array4[16 + i], b), 8));
				}
				Arrays.MemCopy(array4, psDec.subfr_length, array4, 0, 16);
				num4 += psDec.subfr_length;
				num5 += psDec.subfr_length;
			}
			Arrays.MemCopy(array4, 0, psDec.sLPC_Q14_buf, 0, 16);
		}
	}
	internal static class DecodeIndices
	{
		internal static void silk_decode_indices(SilkChannelDecoder psDec, EntropyCoder psRangeDec, ReadOnlySpan<byte> frameData, int FrameIndex, int decode_LBRR, int condCoding)
		{
			short[] array = new short[psDec.LPC_order];
			byte[] array2 = new byte[psDec.LPC_order];
			int num = ((decode_LBRR == 0 && psDec.VAD_flags[FrameIndex] == 0) ? psRangeDec.dec_icdf(frameData, Tables.silk_type_offset_no_VAD_iCDF, 8u) : (psRangeDec.dec_icdf(frameData, Tables.silk_type_offset_VAD_iCDF, 8u) + 2));
			psDec.indices.signalType = (sbyte)Inlines.silk_RSHIFT(num, 1);
			psDec.indices.quantOffsetType = (sbyte)(num & 1);
			if (condCoding == 2)
			{
				psDec.indices.GainsIndices[0] = (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_delta_gain_iCDF, 8u);
			}
			else
			{
				psDec.indices.GainsIndices[0] = (sbyte)Inlines.silk_LSHIFT(psRangeDec.dec_icdf(frameData, Tables.silk_gain_iCDF[psDec.indices.signalType], 8u), 3);
				psDec.indices.GainsIndices[0] += (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_uniform8_iCDF, 8u);
			}
			for (int i = 1; i < psDec.nb_subfr; i++)
			{
				psDec.indices.GainsIndices[i] = (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_delta_gain_iCDF, 8u);
			}
			psDec.indices.NLSFIndices[0] = (sbyte)psRangeDec.dec_icdf(frameData, psDec.psNLSF_CB.CB1_iCDF, (psDec.indices.signalType >> 1) * psDec.psNLSF_CB.nVectors, 8u);
			NLSF.silk_NLSF_unpack(array, array2, psDec.psNLSF_CB, psDec.indices.NLSFIndices[0]);
			for (int i = 0; i < psDec.psNLSF_CB.order; i++)
			{
				num = psRangeDec.dec_icdf(frameData, psDec.psNLSF_CB.ec_iCDF, array[i], 8u);
				switch (num)
				{
				case 0:
					num -= psRangeDec.dec_icdf(frameData, Tables.silk_NLSF_EXT_iCDF, 8u);
					break;
				case 8:
					num += psRangeDec.dec_icdf(frameData, Tables.silk_NLSF_EXT_iCDF, 8u);
					break;
				}
				psDec.indices.NLSFIndices[i + 1] = (sbyte)(num - 4);
			}
			if (psDec.nb_subfr == 4)
			{
				psDec.indices.NLSFInterpCoef_Q2 = (sbyte)psRangeDec.dec_icdf(frameData, Tables.silk_NLSF

Concentus.Oggfile.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using Concentus.Structs;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTrademark("")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Logan Stromberg")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © Logan Stromberg, Andrew Ward")]
[assembly: AssemblyDescription("This package implements file streams which can be used to extract or encode Opus packets in an Ogg-formatted audio file (usually .opus), giving developers a very simple API to perform the task of reading or writing audio files that can be played universally. The Concentus library is used to encode/decode the opus packets automatically. The codec can optionally be accelerated by also referencing the Concentus.Native package.")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyInformationalVersion("1.0.6.0+dee65d9de0ef009658c2d60be6fd9b29d362a482")]
[assembly: AssemblyProduct("Concentus.Oggfile")]
[assembly: AssemblyTitle("Concentus.Oggfile")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/lostromb/concentus.oggfile")]
[assembly: AssemblyVersion("1.0.6.0")]
namespace Concentus.Oggfile;

internal static class BinaryHelpers
{
	internal static void Int16ToByteArrayLittleEndian(short val, byte[] target, int targetOffset)
	{
		UInt16ToByteArrayLittleEndian((ushort)val, target, targetOffset);
	}

	internal static void UInt16ToByteArrayLittleEndian(ushort val, byte[] target, int targetOffset)
	{
		target[targetOffset + 1] = (byte)((uint)(val >> 8) & 0xFFu);
		target[targetOffset] = (byte)(val & 0xFFu);
	}

	internal static void Int16ToByteSpanLittleEndian(short val, ref Span<byte> target)
	{
		UInt16ToByteArraySpanEndian((ushort)val, ref target);
	}

	internal static void UInt16ToByteArraySpanEndian(ushort val, ref Span<byte> target)
	{
		target[1] = (byte)((uint)(val >> 8) & 0xFFu);
		target[0] = (byte)(val & 0xFFu);
	}

	internal static void Int16ToByteArrayBigEndian(short val, byte[] target, int targetOffset)
	{
		UInt16ToByteArrayBigEndian((ushort)val, target, targetOffset);
	}

	internal static void UInt16ToByteArrayBigEndian(ushort val, byte[] target, int targetOffset)
	{
		target[targetOffset] = (byte)((uint)(val >> 8) & 0xFFu);
		target[targetOffset + 1] = (byte)(val & 0xFFu);
	}

	internal static void Int16ToByteSpanBigEndian(short val, ref Span<byte> target)
	{
		UInt16ToByteSpanBigEndian((ushort)val, ref target);
	}

	internal static void UInt16ToByteSpanBigEndian(ushort val, ref Span<byte> target)
	{
		target[0] = (byte)((uint)(val >> 8) & 0xFFu);
		target[1] = (byte)(val & 0xFFu);
	}

	internal static void Int32ToByteArrayLittleEndian(int val, byte[] target, int targetOffset)
	{
		UInt32ToByteArrayLittleEndian((uint)val, target, targetOffset);
	}

	internal static void UInt32ToByteArrayLittleEndian(uint val, byte[] target, int targetOffset)
	{
		target[targetOffset + 3] = (byte)((val >> 24) & 0xFFu);
		target[targetOffset + 2] = (byte)((val >> 16) & 0xFFu);
		target[targetOffset + 1] = (byte)((val >> 8) & 0xFFu);
		target[targetOffset] = (byte)(val & 0xFFu);
	}

	internal static void Int32ToByteSpanLittleEndian(int val, ref Span<byte> target)
	{
		UInt32ToByteSpanLittleEndian((uint)val, ref target);
	}

	internal static void UInt32ToByteSpanLittleEndian(uint val, ref Span<byte> target)
	{
		target[3] = (byte)((val >> 24) & 0xFFu);
		target[2] = (byte)((val >> 16) & 0xFFu);
		target[1] = (byte)((val >> 8) & 0xFFu);
		target[0] = (byte)(val & 0xFFu);
	}

	internal static void UInt24ToByteArrayBigEndian(uint val, byte[] target, int targetOffset)
	{
		target[targetOffset] = (byte)((val >> 16) & 0xFFu);
		target[targetOffset + 1] = (byte)((val >> 8) & 0xFFu);
		target[targetOffset + 2] = (byte)(val & 0xFFu);
	}

	internal static void UInt24ToByteSpanBigEndian(uint val, ref Span<byte> target)
	{
		target[0] = (byte)((val >> 16) & 0xFFu);
		target[1] = (byte)((val >> 8) & 0xFFu);
		target[2] = (byte)(val & 0xFFu);
	}

	internal static void Int32ToByteArrayBigEndian(int val, byte[] target, int targetOffset)
	{
		UInt32ToByteArrayBigEndian((uint)val, target, targetOffset);
	}

	internal static void UInt32ToByteArrayBigEndian(uint val, byte[] target, int targetOffset)
	{
		target[targetOffset] = (byte)((val >> 24) & 0xFFu);
		target[targetOffset + 1] = (byte)((val >> 16) & 0xFFu);
		target[targetOffset + 2] = (byte)((val >> 8) & 0xFFu);
		target[targetOffset + 3] = (byte)(val & 0xFFu);
	}

	internal static void Int32ToByteSpanBigEndian(int val, ref Span<byte> target)
	{
		UInt32ToByteSpanBigEndian((uint)val, ref target);
	}

	internal static void UInt32ToByteSpanBigEndian(uint val, ref Span<byte> target)
	{
		target[0] = (byte)((val >> 24) & 0xFFu);
		target[1] = (byte)((val >> 16) & 0xFFu);
		target[2] = (byte)((val >> 8) & 0xFFu);
		target[3] = (byte)(val & 0xFFu);
	}

	internal static void Int64ToByteArrayLittleEndian(long val, byte[] target, int targetOffset)
	{
		UInt64ToByteArrayLittleEndian((ulong)val, target, targetOffset);
	}

	internal static void UInt64ToByteArrayLittleEndian(ulong val, byte[] target, int targetOffset)
	{
		target[targetOffset + 7] = (byte)((val >> 56) & 0xFF);
		target[targetOffset + 6] = (byte)((val >> 48) & 0xFF);
		target[targetOffset + 5] = (byte)((val >> 40) & 0xFF);
		target[targetOffset + 4] = (byte)((val >> 32) & 0xFF);
		target[targetOffset + 3] = (byte)((val >> 24) & 0xFF);
		target[targetOffset + 2] = (byte)((val >> 16) & 0xFF);
		target[targetOffset + 1] = (byte)((val >> 8) & 0xFF);
		target[targetOffset] = (byte)(val & 0xFF);
	}

	internal static void Int64ToByteSpanLittleEndian(long val, ref Span<byte> target)
	{
		UInt64ToByteSpanLittleEndian((ulong)val, ref target);
	}

	internal static void UInt64ToByteSpanLittleEndian(ulong val, ref Span<byte> target)
	{
		target[7] = (byte)((val >> 56) & 0xFF);
		target[6] = (byte)((val >> 48) & 0xFF);
		target[5] = (byte)((val >> 40) & 0xFF);
		target[4] = (byte)((val >> 32) & 0xFF);
		target[3] = (byte)((val >> 24) & 0xFF);
		target[2] = (byte)((val >> 16) & 0xFF);
		target[1] = (byte)((val >> 8) & 0xFF);
		target[0] = (byte)(val & 0xFF);
	}

	internal static void Int64ToByteArrayBigEndian(long val, byte[] target, int targetOffset)
	{
		UInt64ToByteArrayBigEndian((ulong)val, target, targetOffset);
	}

	internal static void UInt64ToByteArrayBigEndian(ulong val, byte[] target, int targetOffset)
	{
		target[targetOffset] = (byte)((val >> 56) & 0xFF);
		target[targetOffset + 1] = (byte)((val >> 48) & 0xFF);
		target[targetOffset + 2] = (byte)((val >> 40) & 0xFF);
		target[targetOffset + 3] = (byte)((val >> 32) & 0xFF);
		target[targetOffset + 4] = (byte)((val >> 24) & 0xFF);
		target[targetOffset + 5] = (byte)((val >> 16) & 0xFF);
		target[targetOffset + 6] = (byte)((val >> 8) & 0xFF);
		target[targetOffset + 7] = (byte)(val & 0xFF);
	}

	internal static void Int64ToByteSpanBigEndian(long val, ref Span<byte> target)
	{
		UInt64ToByteSpanBigEndian((ulong)val, ref target);
	}

	internal static void UInt64ToByteSpanBigEndian(ulong val, ref Span<byte> target)
	{
		target[0] = (byte)((val >> 56) & 0xFF);
		target[1] = (byte)((val >> 48) & 0xFF);
		target[2] = (byte)((val >> 40) & 0xFF);
		target[3] = (byte)((val >> 32) & 0xFF);
		target[4] = (byte)((val >> 24) & 0xFF);
		target[5] = (byte)((val >> 16) & 0xFF);
		target[6] = (byte)((val >> 8) & 0xFF);
		target[7] = (byte)(val & 0xFF);
	}

	internal static short ByteArrayToInt16LittleEndian(byte[] source, int offset)
	{
		return (short)((short)(0 | (short)(source[offset + 1] << 8)) | (short)source[offset]);
	}

	internal static short ByteSpanToInt16LittleEndian(ref Span<byte> source)
	{
		return (short)((short)(0 | (short)(source[1] << 8)) | (short)source[0]);
	}

	internal static short ByteSpanToInt16LittleEndian(ref ReadOnlySpan<byte> source)
	{
		return (short)((short)(0 | (short)(source[1] << 8)) | (short)source[0]);
	}

	internal static ushort ByteArrayToUInt16LittleEndian(byte[] source, int offset)
	{
		return (ushort)((ushort)(0u | (ushort)(source[offset + 1] << 8)) | source[offset]);
	}

	internal static ushort ByteSpanToUInt16LittleEndian(ref Span<byte> source)
	{
		return (ushort)((ushort)(0u | (ushort)(source[1] << 8)) | source[0]);
	}

	internal static ushort ByteSpanToUInt16LittleEndian(ref ReadOnlySpan<byte> source)
	{
		return (ushort)((ushort)(0u | (ushort)(source[1] << 8)) | source[0]);
	}

	internal static short ByteArrayToInt16BigEndian(byte[] source, int offset)
	{
		return (short)((short)(0 | (short)(source[offset] << 8)) | (short)source[offset + 1]);
	}

	internal static short ByteSpanToInt16BigEndian(ref Span<byte> source)
	{
		return (short)((short)(0 | (short)(source[0] << 8)) | (short)source[1]);
	}

	internal static short ByteSpanToInt16BigEndian(ref ReadOnlySpan<byte> source)
	{
		return (short)((short)(0 | (short)(source[0] << 8)) | (short)source[1]);
	}

	internal static ushort ByteArrayToUInt16BigEndian(byte[] source, int offset)
	{
		return (ushort)((ushort)(0u | (ushort)(source[offset] << 8)) | source[offset + 1]);
	}

	internal static ushort ByteSpanToUInt16BigEndian(ref Span<byte> source)
	{
		return (ushort)((ushort)(0u | (ushort)(source[0] << 8)) | source[1]);
	}

	internal static ushort ByteSpanToUInt16BigEndian(ref ReadOnlySpan<byte> source)
	{
		return (ushort)((ushort)(0u | (ushort)(source[0] << 8)) | source[1]);
	}

	internal static int ByteArrayToInt32LittleEndian(byte[] source, int offset)
	{
		return 0 | (source[offset + 3] << 24) | (source[offset + 2] << 16) | (source[offset + 1] << 8) | source[offset];
	}

	internal static int ByteSpanToInt32LittleEndian(ref Span<byte> source)
	{
		return 0 | (source[3] << 24) | (source[2] << 16) | (source[1] << 8) | source[0];
	}

	internal static int ByteSpanToInt32LittleEndian(ref ReadOnlySpan<byte> source)
	{
		return 0 | (source[3] << 24) | (source[2] << 16) | (source[1] << 8) | source[0];
	}

	internal static uint ByteArrayToUInt32LittleEndian(byte[] source, int offset)
	{
		return 0u | (uint)(source[offset + 3] << 24) | (uint)(source[offset + 2] << 16) | (uint)(source[offset + 1] << 8) | source[offset];
	}

	internal static uint ByteSpanToUInt32LittleEndian(ref Span<byte> source)
	{
		return 0u | (uint)(source[3] << 24) | (uint)(source[2] << 16) | (uint)(source[1] << 8) | source[0];
	}

	internal static uint ByteSpanToUInt32LittleEndian(ref ReadOnlySpan<byte> source)
	{
		return 0u | (uint)(source[3] << 24) | (uint)(source[2] << 16) | (uint)(source[1] << 8) | source[0];
	}

	internal static uint ByteArrayToUInt24BigEndian(byte[] source, int offset)
	{
		return 0u | (uint)(source[offset] << 16) | (uint)(source[offset + 1] << 8) | source[offset + 2];
	}

	internal static uint ByteSpanToUInt24BigEndian(ref Span<byte> source)
	{
		return 0u | (uint)(source[0] << 16) | (uint)(source[1] << 8) | source[2];
	}

	internal static uint ByteSpanToUInt24BigEndian(ref ReadOnlySpan<byte> source)
	{
		return 0u | (uint)(source[0] << 16) | (uint)(source[1] << 8) | source[2];
	}

	internal static int ByteArrayToInt32BigEndian(byte[] source, int offset)
	{
		return 0 | (source[offset] << 24) | (source[offset + 1] << 16) | (source[offset + 2] << 8) | source[offset + 3];
	}

	internal static int ByteSpanToInt32BigEndian(ref Span<byte> source)
	{
		return 0 | (source[0] << 24) | (source[1] << 16) | (source[2] << 8) | source[3];
	}

	internal static int ByteSpanToInt32BigEndian(ref ReadOnlySpan<byte> source)
	{
		return 0 | (source[0] << 24) | (source[1] << 16) | (source[2] << 8) | source[3];
	}

	internal static uint ByteArrayToUInt32BigEndian(byte[] source, int offset)
	{
		return 0u | (uint)(source[offset] << 24) | (uint)(source[offset + 1] << 16) | (uint)(source[offset + 2] << 8) | source[offset + 3];
	}

	internal static uint ByteSpanToUInt32BigEndian(ref Span<byte> source)
	{
		return 0u | (uint)(source[0] << 24) | (uint)(source[1] << 16) | (uint)(source[2] << 8) | source[3];
	}

	internal static uint ByteSpanToUInt32BigEndian(ref ReadOnlySpan<byte> source)
	{
		return 0u | (uint)(source[0] << 24) | (uint)(source[1] << 16) | (uint)(source[2] << 8) | source[3];
	}

	internal static long ByteArrayToInt64LittleEndian(byte[] source, int offset)
	{
		return (long)(0 | ((ulong)source[offset + 7] << 56) | ((ulong)source[offset + 6] << 48) | ((ulong)source[offset + 5] << 40) | ((ulong)source[offset + 4] << 32) | ((ulong)source[offset + 3] << 24) | ((ulong)source[offset + 2] << 16) | ((ulong)source[offset + 1] << 8) | source[offset]);
	}

	internal static long ByteSpanToInt64LittleEndian(ref Span<byte> source)
	{
		return (long)(0 | ((ulong)source[7] << 56) | ((ulong)source[6] << 48) | ((ulong)source[5] << 40) | ((ulong)source[4] << 32) | ((ulong)source[3] << 24) | ((ulong)source[2] << 16) | ((ulong)source[1] << 8) | source[0]);
	}

	internal static long ByteSpanToInt64LittleEndian(ref ReadOnlySpan<byte> source)
	{
		return (long)(0 | ((ulong)source[7] << 56) | ((ulong)source[6] << 48) | ((ulong)source[5] << 40) | ((ulong)source[4] << 32) | ((ulong)source[3] << 24) | ((ulong)source[2] << 16) | ((ulong)source[1] << 8) | source[0]);
	}

	internal static ulong ByteArrayToUInt64LittleEndian(byte[] source, int offset)
	{
		return 0 | ((ulong)source[offset + 7] << 56) | ((ulong)source[offset + 6] << 48) | ((ulong)source[offset + 5] << 40) | ((ulong)source[offset + 4] << 32) | ((ulong)source[offset + 3] << 24) | ((ulong)source[offset + 2] << 16) | ((ulong)source[offset + 1] << 8) | source[offset];
	}

	internal static ulong ByteSpanToUInt64LittleEndian(ref Span<byte> source)
	{
		return 0 | ((ulong)source[7] << 56) | ((ulong)source[6] << 48) | ((ulong)source[5] << 40) | ((ulong)source[4] << 32) | ((ulong)source[3] << 24) | ((ulong)source[2] << 16) | ((ulong)source[1] << 8) | source[0];
	}

	internal static ulong ByteSpanToUInt64LittleEndian(ref ReadOnlySpan<byte> source)
	{
		return 0 | ((ulong)source[7] << 56) | ((ulong)source[6] << 48) | ((ulong)source[5] << 40) | ((ulong)source[4] << 32) | ((ulong)source[3] << 24) | ((ulong)source[2] << 16) | ((ulong)source[1] << 8) | source[0];
	}

	internal static long ByteArrayToInt64BigEndian(byte[] source, int offset)
	{
		return (long)(0 | ((ulong)source[offset] << 56) | ((ulong)source[offset + 1] << 48) | ((ulong)source[offset + 2] << 40) | ((ulong)source[offset + 3] << 32) | ((ulong)source[offset + 4] << 24) | ((ulong)source[offset + 5] << 16) | ((ulong)source[offset + 6] << 8) | source[offset + 7]);
	}

	internal static long ByteSpanToInt64BigEndian(ref Span<byte> source)
	{
		return (long)(0 | ((ulong)source[0] << 56) | ((ulong)source[1] << 48) | ((ulong)source[2] << 40) | ((ulong)source[3] << 32) | ((ulong)source[4] << 24) | ((ulong)source[5] << 16) | ((ulong)source[6] << 8) | source[7]);
	}

	internal static long ByteSpanToInt64BigEndian(ref ReadOnlySpan<byte> source)
	{
		return (long)(0 | ((ulong)source[0] << 56) | ((ulong)source[1] << 48) | ((ulong)source[2] << 40) | ((ulong)source[3] << 32) | ((ulong)source[4] << 24) | ((ulong)source[5] << 16) | ((ulong)source[6] << 8) | source[7]);
	}

	internal static ulong ByteArrayToUInt64BigEndian(byte[] source, int offset)
	{
		return 0 | ((ulong)source[offset] << 56) | ((ulong)source[offset + 1] << 48) | ((ulong)source[offset + 2] << 40) | ((ulong)source[offset + 3] << 32) | ((ulong)source[offset + 4] << 24) | ((ulong)source[offset + 5] << 16) | ((ulong)source[offset + 6] << 8) | source[offset + 7];
	}

	internal static ulong ByteSpanToUInt64BigEndian(ref Span<byte> source)
	{
		return 0 | ((ulong)source[0] << 56) | ((ulong)source[1] << 48) | ((ulong)source[2] << 40) | ((ulong)source[3] << 32) | ((ulong)source[4] << 24) | ((ulong)source[5] << 16) | ((ulong)source[6] << 8) | source[7];
	}

	internal static ulong ByteSpanToUInt64BigEndian(ref ReadOnlySpan<byte> source)
	{
		return 0 | ((ulong)source[0] << 56) | ((ulong)source[1] << 48) | ((ulong)source[2] << 40) | ((ulong)source[3] << 32) | ((ulong)source[4] << 24) | ((ulong)source[5] << 16) | ((ulong)source[6] << 8) | source[7];
	}
}
internal class BufferedReadStream : Stream
{
	private const int DEFAULT_INITIAL_SIZE = 32768;

	private const int DEFAULT_MAX_SIZE = 262144;

	private Stream _baseStream;

	private StreamReadBuffer _buffer;

	private long _readPosition;

	public bool CloseBaseStream { get; set; }

	public bool MinimalRead
	{
		get
		{
			return _buffer.MinimalRead;
		}
		set
		{
			_buffer.MinimalRead = value;
		}
	}

	public int MaxBufferSize
	{
		get
		{
			return _buffer.MaxSize;
		}
		set
		{
			CheckLock();
			_buffer.MaxSize = value;
		}
	}

	public long BufferBaseOffset => _buffer.BaseOffset;

	public int BufferBytesFilled => _buffer.BytesFilled;

	public override bool CanRead => true;

	public override bool CanSeek => true;

	public override bool CanWrite => false;

	public override long Length => _baseStream.Length;

	public override long Position
	{
		get
		{
			return _readPosition;
		}
		set
		{
			Seek(value, SeekOrigin.Begin);
		}
	}

	public BufferedReadStream(Stream baseStream)
		: this(baseStream, 32768, 262144, minimalRead: false)
	{
	}

	public BufferedReadStream(Stream baseStream, bool minimalRead)
		: this(baseStream, 32768, 262144, minimalRead)
	{
	}

	public BufferedReadStream(Stream baseStream, int initialSize, int maxSize)
		: this(baseStream, initialSize, maxSize, minimalRead: false)
	{
	}

	public BufferedReadStream(Stream baseStream, int initialSize, int maxBufferSize, bool minimalRead)
	{
		if (baseStream == null)
		{
			throw new ArgumentNullException("baseStream");
		}
		if (!baseStream.CanRead)
		{
			throw new ArgumentException("baseStream");
		}
		if (maxBufferSize < 1)
		{
			maxBufferSize = 1;
		}
		if (initialSize < 1)
		{
			initialSize = 1;
		}
		if (initialSize > maxBufferSize)
		{
			initialSize = maxBufferSize;
		}
		_baseStream = baseStream;
		_buffer = new StreamReadBuffer(baseStream, initialSize, maxBufferSize, minimalRead);
		_buffer.MaxSize = maxBufferSize;
		_buffer.MinimalRead = minimalRead;
	}

	protected override void Dispose(bool disposing)
	{
		base.Dispose(disposing);
		if (disposing)
		{
			if (_buffer != null)
			{
				_buffer.Dispose();
				_buffer = null;
			}
			_ = CloseBaseStream;
		}
	}

	public void TakeLock()
	{
	}

	private void CheckLock()
	{
	}

	public void ReleaseLock()
	{
	}

	public void Discard(int bytes)
	{
		CheckLock();
		_buffer.DiscardThrough(_buffer.BaseOffset + bytes);
	}

	public void DiscardThrough(long offset)
	{
		CheckLock();
		_buffer.DiscardThrough(offset);
	}

	public override void Flush()
	{
	}

	public override int ReadByte()
	{
		CheckLock();
		int num = _buffer.ReadByte(Position);
		if (num > -1)
		{
			Seek(1L, SeekOrigin.Current);
		}
		return num;
	}

	public override int Read(byte[] buffer, int offset, int count)
	{
		CheckLock();
		int num = _buffer.Read(Position, buffer, offset, count);
		Seek(num, SeekOrigin.Current);
		return num;
	}

	public override long Seek(long offset, SeekOrigin origin)
	{
		CheckLock();
		switch (origin)
		{
		case SeekOrigin.Current:
			offset += Position;
			break;
		case SeekOrigin.End:
			offset += _baseStream.Length;
			break;
		}
		if (!_baseStream.CanSeek)
		{
			if (offset < _buffer.BaseOffset)
			{
				throw new InvalidOperationException("Cannot seek to before the start of the buffer!");
			}
			if (offset > _buffer.BufferEndOffset)
			{
				throw new InvalidOperationException("Cannot seek to beyond the end of the buffer!  Discard some bytes.");
			}
		}
		return _readPosition = offset;
	}

	public override void SetLength(long value)
	{
		throw new NotSupportedException();
	}

	public override void Write(byte[] buffer, int offset, int count)
	{
		throw new NotSupportedException();
	}
}
internal abstract class DataPacket
{
	[Flags]
	protected enum PacketFlags : byte
	{
		IsResync = 1,
		IsEndOfStream = 2,
		IsShort = 4,
		HasGranuleCount = 8,
		User1 = 0x10,
		User2 = 0x20,
		User3 = 0x40,
		User4 = 0x80
	}

	private ulong _bitBucket;

	private int _bitCount;

	private int _readBits;

	private byte _overflowBits;

	private PacketFlags _packetFlags;

	private long _granulePosition;

	private long _pageGranulePosition;

	private int _length;

	private int _granuleCount;

	private int _pageSequenceNumber;

	public bool IsResync
	{
		get
		{
			return GetFlag(PacketFlags.IsResync);
		}
		internal set
		{
			SetFlag(PacketFlags.IsResync, value);
		}
	}

	public long GranulePosition
	{
		get
		{
			return _granulePosition;
		}
		set
		{
			_granulePosition = value;
		}
	}

	public long PageGranulePosition
	{
		get
		{
			return _pageGranulePosition;
		}
		internal set
		{
			_pageGranulePosition = value;
		}
	}

	public int Length
	{
		get
		{
			return _length;
		}
		protected set
		{
			_length = value;
		}
	}

	public bool IsEndOfStream
	{
		get
		{
			return GetFlag(PacketFlags.IsEndOfStream);
		}
		internal set
		{
			SetFlag(PacketFlags.IsEndOfStream, value);
		}
	}

	public long BitsRead => _readBits;

	public int? GranuleCount
	{
		get
		{
			if (GetFlag(PacketFlags.HasGranuleCount))
			{
				return _granuleCount;
			}
			return null;
		}
		set
		{
			if (value.HasValue)
			{
				_granuleCount = value.Value;
				SetFlag(PacketFlags.HasGranuleCount, value: true);
			}
			else
			{
				SetFlag(PacketFlags.HasGranuleCount, value: false);
			}
		}
	}

	internal int PageSequenceNumber
	{
		get
		{
			return _pageSequenceNumber;
		}
		set
		{
			_pageSequenceNumber = value;
		}
	}

	internal bool IsShort
	{
		get
		{
			return GetFlag(PacketFlags.IsShort);
		}
		private set
		{
			SetFlag(PacketFlags.IsShort, value);
		}
	}

	protected bool GetFlag(PacketFlags flag)
	{
		return (_packetFlags & flag) == flag;
	}

	protected void SetFlag(PacketFlags flag, bool value)
	{
		if (value)
		{
			_packetFlags |= flag;
		}
		else
		{
			_packetFlags &= (PacketFlags)(byte)(~(int)flag);
		}
	}

	protected DataPacket(int length)
	{
		Length = length;
	}

	protected abstract int ReadNextByte();

	public virtual void Done()
	{
	}

	public ulong TryPeekBits(int count, out int bitsRead)
	{
		ulong num = 0uL;
		switch (count)
		{
		default:
			throw new ArgumentOutOfRangeException("count");
		case 0:
			bitsRead = 0;
			return 0uL;
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:
		case 9:
		case 10:
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
		case 16:
		case 17:
		case 18:
		case 19:
		case 20:
		case 21:
		case 22:
		case 23:
		case 24:
		case 25:
		case 26:
		case 27:
		case 28:
		case 29:
		case 30:
		case 31:
		case 32:
		case 33:
		case 34:
		case 35:
		case 36:
		case 37:
		case 38:
		case 39:
		case 40:
		case 41:
		case 42:
		case 43:
		case 44:
		case 45:
		case 46:
		case 47:
		case 48:
		case 49:
		case 50:
		case 51:
		case 52:
		case 53:
		case 54:
		case 55:
		case 56:
		case 57:
		case 58:
		case 59:
		case 60:
		case 61:
		case 62:
		case 63:
		case 64:
			break;
		}
		while (_bitCount < count)
		{
			int num2 = ReadNextByte();
			if (num2 == -1)
			{
				bitsRead = _bitCount;
				num = _bitBucket;
				_bitBucket = 0uL;
				_bitCount = 0;
				IsShort = true;
				return num;
			}
			_bitBucket = (ulong)((long)(num2 & 0xFF) << _bitCount) | _bitBucket;
			_bitCount += 8;
			if (_bitCount > 64)
			{
				_overflowBits = (byte)(num2 >> 72 - _bitCount);
			}
		}
		num = _bitBucket;
		if (count < 64)
		{
			num &= (ulong)((1L << count) - 1);
		}
		bitsRead = count;
		return num;
	}

	public void SkipBits(int count)
	{
		if (count == 0)
		{
			return;
		}
		if (_bitCount > count)
		{
			if (count > 63)
			{
				_bitBucket = 0uL;
			}
			else
			{
				_bitBucket >>= count;
			}
			if (_bitCount > 64)
			{
				int num = _bitCount - 64;
				_bitBucket |= (ulong)_overflowBits << _bitCount - count - num;
				if (num > count)
				{
					_overflowBits = (byte)(_overflowBits >> count);
				}
			}
			_bitCount -= count;
			_readBits += count;
			return;
		}
		if (_bitCount == count)
		{
			_bitBucket = 0uL;
			_bitCount = 0;
			_readBits += count;
			return;
		}
		count -= _bitCount;
		_readBits += _bitCount;
		_bitCount = 0;
		_bitBucket = 0uL;
		while (count > 8)
		{
			if (ReadNextByte() == -1)
			{
				count = 0;
				IsShort = true;
				break;
			}
			count -= 8;
			_readBits += 8;
		}
		if (count > 0)
		{
			int num2 = ReadNextByte();
			if (num2 == -1)
			{
				IsShort = true;
				return;
			}
			_bitBucket = (ulong)(num2 >> count);
			_bitCount = 8 - count;
			_readBits += count;
		}
	}

	protected void ResetBitReader()
	{
		_bitBucket = 0uL;
		_bitCount = 0;
		_readBits = 0;
		IsShort = false;
	}

	public ulong ReadBits(int count)
	{
		if (count == 0)
		{
			return 0uL;
		}
		int bitsRead;
		ulong result = TryPeekBits(count, out bitsRead);
		SkipBits(count);
		return result;
	}

	public byte PeekByte()
	{
		int bitsRead;
		return (byte)TryPeekBits(8, out bitsRead);
	}

	public byte ReadByte()
	{
		return (byte)ReadBits(8);
	}

	public byte[] ReadBytes(int count)
	{
		List<byte> list = new List<byte>(count);
		while (list.Count < count)
		{
			list.Add(ReadByte());
		}
		return list.ToArray();
	}

	public int Read(byte[] buffer, int index, int count)
	{
		if (index < 0 || index + count > buffer.Length)
		{
			throw new ArgumentOutOfRangeException("index");
		}
		for (int i = 0; i < count; i++)
		{
			int bitsRead;
			byte b = (byte)TryPeekBits(8, out bitsRead);
			if (bitsRead == 0)
			{
				return i;
			}
			buffer[index++] = b;
			SkipBits(8);
		}
		return count;
	}

	public bool ReadBit()
	{
		return ReadBits(1) == 1;
	}

	public short ReadInt16()
	{
		return (short)ReadBits(16);
	}

	public int ReadInt32()
	{
		return (int)ReadBits(32);
	}

	public long ReadInt64()
	{
		return (long)ReadBits(64);
	}

	public ushort ReadUInt16()
	{
		return (ushort)ReadBits(16);
	}

	public uint ReadUInt32()
	{
		return (uint)ReadBits(32);
	}

	public ulong ReadUInt64()
	{
		return ReadBits(64);
	}

	public void SkipBytes(int count)
	{
		SkipBits(count * 8);
	}
}
internal interface IContainerReader : IDisposable
{
	int[] StreamSerials { get; }

	bool CanSeek { get; }

	long WasteBits { get; }

	int PagesRead { get; }

	event EventHandler<NewStreamEventArgs> NewStream;

	bool Init();

	bool FindNextStream();

	int GetTotalPageCount();
}
internal interface IPacketProvider : IDisposable
{
	int StreamSerial { get; }

	bool CanSeek { get; }

	long ContainerBits { get; }

	event EventHandler<ParameterChangeEventArgs> ParameterChange;

	int GetTotalPageCount();

	DataPacket GetNextPacket();

	DataPacket PeekNextPacket();

	DataPacket GetPacket(int packetIndex);

	long GetGranuleCount();

	DataPacket FindPacket(long granulePos, Func<DataPacket, DataPacket, int> packetGranuleCountCallback);

	void SeekToPacket(DataPacket packet, int preRoll);
}
internal class NewStreamEventArgs : EventArgs
{
	public IPacketProvider PacketProvider { get; private set; }

	public bool IgnoreStream { get; set; }

	public NewStreamEventArgs(IPacketProvider packetProvider)
	{
		if (packetProvider == null)
		{
			throw new ArgumentNullException("packetProvider");
		}
		PacketProvider = packetProvider;
	}
}
internal class OggContainerReader : IContainerReader, IDisposable
{
	private class PageHeader
	{
		public int StreamSerial { get; set; }

		public PageFlags Flags { get; set; }

		public long GranulePosition { get; set; }

		public int SequenceNumber { get; set; }

		public long DataOffset { get; set; }

		public int[] PacketSizes { get; set; }

		public bool LastPacketContinues { get; set; }

		public bool IsResync { get; set; }
	}

	private Crc _crc = new Crc();

	private BufferedReadStream _stream;

	private Dictionary<int, PacketReader> _packetReaders;

	private List<int> _disposedStreamSerials;

	private long _nextPageOffset;

	private int _pageCount;

	private byte[] _readBuffer = new byte[65025];

	private long _containerBits;

	private long _wasteBits;

	public int[] StreamSerials => _packetReaders.Keys.ToArray();

	public int PagesRead => _pageCount;

	public bool CanSeek => _stream.CanSeek;

	public long WasteBits => _wasteBits;

	public event EventHandler<NewStreamEventArgs> NewStream;

	public OggContainerReader(Stream stream, bool closeOnDispose)
	{
		_packetReaders = new Dictionary<int, PacketReader>();
		_disposedStreamSerials = new List<int>();
		_stream = (stream as BufferedReadStream) ?? new BufferedReadStream(stream)
		{
			CloseBaseStream = closeOnDispose
		};
	}

	public bool Init()
	{
		_stream.TakeLock();
		try
		{
			return GatherNextPage() != -1;
		}
		finally
		{
			_stream.ReleaseLock();
		}
	}

	public void Dispose()
	{
		int[] streamSerials = StreamSerials;
		foreach (int key in streamSerials)
		{
			_packetReaders[key].Dispose();
		}
		_nextPageOffset = 0L;
		_containerBits = 0L;
		_wasteBits = 0L;
		_stream.Dispose();
	}

	public IPacketProvider GetStream(int streamSerial)
	{
		if (!_packetReaders.TryGetValue(streamSerial, out var value))
		{
			throw new ArgumentOutOfRangeException("streamSerial");
		}
		return value;
	}

	public bool FindNextStream()
	{
		if (!CanSeek)
		{
			throw new InvalidOperationException();
		}
		int count = _packetReaders.Count;
		while (_packetReaders.Count == count)
		{
			_stream.TakeLock();
			try
			{
				if (GatherNextPage() == -1)
				{
					break;
				}
			}
			finally
			{
				_stream.ReleaseLock();
			}
		}
		return count > _packetReaders.Count;
	}

	public int GetTotalPageCount()
	{
		if (!CanSeek)
		{
			throw new InvalidOperationException();
		}
		while (true)
		{
			_stream.TakeLock();
			try
			{
				if (GatherNextPage() == -1)
				{
					break;
				}
			}
			finally
			{
				_stream.ReleaseLock();
			}
		}
		return _pageCount;
	}

	private PageHeader ReadPageHeader(long position)
	{
		_stream.Seek(position, SeekOrigin.Begin);
		if (_stream.Read(_readBuffer, 0, 27) != 27)
		{
			return null;
		}
		if (_readBuffer[0] != 79 || _readBuffer[1] != 103 || _readBuffer[2] != 103 || _readBuffer[3] != 83)
		{
			return null;
		}
		if (_readBuffer[4] != 0)
		{
			return null;
		}
		PageHeader pageHeader = new PageHeader();
		pageHeader.Flags = (PageFlags)_readBuffer[5];
		pageHeader.GranulePosition = BitConverter.ToInt64(_readBuffer, 6);
		pageHeader.StreamSerial = BitConverter.ToInt32(_readBuffer, 14);
		pageHeader.SequenceNumber = BitConverter.ToInt32(_readBuffer, 18);
		uint checkCrc = BitConverter.ToUInt32(_readBuffer, 22);
		_crc.Reset();
		for (int i = 0; i < 22; i++)
		{
			_crc.Update(_readBuffer[i]);
		}
		_crc.Update(0);
		_crc.Update(0);
		_crc.Update(0);
		_crc.Update(0);
		_crc.Update(_readBuffer[26]);
		int num = _readBuffer[26];
		if (_stream.Read(_readBuffer, 0, num) != num)
		{
			return null;
		}
		List<int> list = new List<int>(num);
		int num2 = 0;
		int num3 = 0;
		for (int j = 0; j < num; j++)
		{
			byte b = _readBuffer[j];
			_crc.Update(b);
			if (num3 == list.Count)
			{
				list.Add(0);
			}
			list[num3] += b;
			if (b < byte.MaxValue)
			{
				num3++;
				pageHeader.LastPacketContinues = false;
			}
			else
			{
				pageHeader.LastPacketContinues = true;
			}
			num2 += b;
		}
		pageHeader.PacketSizes = list.ToArray();
		pageHeader.DataOffset = position + 27 + num;
		if (_stream.Read(_readBuffer, 0, num2) != num2)
		{
			return null;
		}
		for (int k = 0; k < num2; k++)
		{
			_crc.Update(_readBuffer[k]);
		}
		if (_crc.Test(checkCrc))
		{
			_containerBits += 8 * (27 + num);
			_pageCount++;
			return pageHeader;
		}
		return null;
	}

	private PageHeader FindNextPageHeader()
	{
		long num = _nextPageOffset;
		bool isResync = false;
		PageHeader pageHeader;
		while ((pageHeader = ReadPageHeader(num)) == null)
		{
			isResync = true;
			_wasteBits += 8L;
			num = (_stream.Position = num + 1);
			int num3 = 0;
			do
			{
				switch (_stream.ReadByte())
				{
				case 79:
					if (_stream.ReadByte() == 103 && _stream.ReadByte() == 103 && _stream.ReadByte() == 83)
					{
						num += num3;
						goto end_IL_0032;
					}
					_stream.Seek(-3L, SeekOrigin.Current);
					break;
				case -1:
					return null;
				}
				_wasteBits += 8L;
				continue;
				end_IL_0032:
				break;
			}
			while (++num3 < 65536);
			if (num3 == 65536)
			{
				return null;
			}
		}
		pageHeader.IsResync = isResync;
		_nextPageOffset = pageHeader.DataOffset;
		for (int i = 0; i < pageHeader.PacketSizes.Length; i++)
		{
			_nextPageOffset += pageHeader.PacketSizes[i];
		}
		return pageHeader;
	}

	private bool AddPage(PageHeader hdr)
	{
		if (!_packetReaders.TryGetValue(hdr.StreamSerial, out var value))
		{
			value = new PacketReader(this, hdr.StreamSerial);
		}
		value.ContainerBits += _containerBits;
		_containerBits = 0L;
		bool isContinued = hdr.PacketSizes.Length == 1 && hdr.LastPacketContinues;
		bool isContinuation = (hdr.Flags & PageFlags.ContinuesPacket) == PageFlags.ContinuesPacket;
		bool isEndOfStream = false;
		bool isResync = hdr.IsResync;
		long num = hdr.DataOffset;
		int num2 = hdr.PacketSizes.Length;
		int[] packetSizes = hdr.PacketSizes;
		foreach (int num3 in packetSizes)
		{
			Packet packet = new Packet(this, num, num3)
			{
				PageGranulePosition = hdr.GranulePosition,
				IsEndOfStream = isEndOfStream,
				PageSequenceNumber = hdr.SequenceNumber,
				IsContinued = isContinued,
				IsContinuation = isContinuation,
				IsResync = isResync
			};
			value.AddPacket(packet);
			num += num3;
			isContinuation = false;
			isResync = false;
			if (--num2 == 1)
			{
				isContinued = hdr.LastPacketContinues;
				isEndOfStream = (hdr.Flags & PageFlags.EndOfStream) == PageFlags.EndOfStream;
			}
		}
		if (!_packetReaders.ContainsKey(hdr.StreamSerial))
		{
			_packetReaders.Add(hdr.StreamSerial, value);
			return true;
		}
		return false;
	}

	private int GatherNextPage()
	{
		PageHeader pageHeader;
		while (true)
		{
			pageHeader = FindNextPageHeader();
			if (pageHeader == null)
			{
				return -1;
			}
			if (!_disposedStreamSerials.Contains(pageHeader.StreamSerial))
			{
				if (!AddPage(pageHeader))
				{
					break;
				}
				EventHandler<NewStreamEventArgs> newStream = this.NewStream;
				if (newStream == null)
				{
					break;
				}
				NewStreamEventArgs newStreamEventArgs = new NewStreamEventArgs(_packetReaders[pageHeader.StreamSerial]);
				newStream(this, newStreamEventArgs);
				if (!newStreamEventArgs.IgnoreStream)
				{
					break;
				}
				_packetReaders[pageHeader.StreamSerial].Dispose();
			}
		}
		return pageHeader.StreamSerial;
	}

	internal void DisposePacketReader(PacketReader packetReader)
	{
		_disposedStreamSerials.Add(packetReader.StreamSerial);
		_packetReaders.Remove(packetReader.StreamSerial);
	}

	internal int PacketReadByte(long offset)
	{
		_stream.TakeLock();
		try
		{
			_stream.Position = offset;
			return _stream.ReadByte();
		}
		finally
		{
			_stream.ReleaseLock();
		}
	}

	internal void PacketDiscardThrough(long offset)
	{
		_stream.TakeLock();
		try
		{
			_stream.DiscardThrough(offset);
		}
		finally
		{
			_stream.ReleaseLock();
		}
	}

	internal void GatherNextPage(int streamSerial)
	{
		if (!_packetReaders.ContainsKey(streamSerial))
		{
			throw new ArgumentOutOfRangeException("streamSerial");
		}
		int num;
		do
		{
			_stream.TakeLock();
			try
			{
				if (_packetReaders[streamSerial].HasEndOfStream)
				{
					break;
				}
				num = GatherNextPage();
				if (num != -1)
				{
					continue;
				}
				foreach (KeyValuePair<int, PacketReader> packetReader in _packetReaders)
				{
					if (!packetReader.Value.HasEndOfStream)
					{
						packetReader.Value.SetEndOfStream();
					}
				}
				break;
			}
			finally
			{
				_stream.ReleaseLock();
			}
		}
		while (num != streamSerial);
	}
}
internal class Crc
{
	private const uint CRC32_POLY = 79764919u;

	private static uint[] crcTable;

	private uint _crc;

	public uint Value => _crc;

	static Crc()
	{
		crcTable = new uint[256];
		for (uint num = 0u; num < 256; num++)
		{
			uint num2 = num << 24;
			for (int i = 0; i < 8; i++)
			{
				num2 = (num2 << 1) ^ ((num2 >= 2147483648u) ? 79764919u : 0u);
			}
			crcTable[num] = num2;
		}
	}

	public Crc()
	{
		Reset();
	}

	public void Reset()
	{
		_crc = 0u;
	}

	public void Update(int nextVal)
	{
		_crc = (_crc << 8) ^ crcTable[nextVal ^ (_crc >> 24)];
	}

	public bool Test(uint checkCrc)
	{
		return _crc == checkCrc;
	}
}
internal class Packet : DataPacket
{
	private long _offset;

	private int _length;

	private int _curOfs;

	private Packet _mergedPacket;

	private Packet _next;

	private Packet _prev;

	private OggContainerReader _containerReader;

	internal Packet Next
	{
		get
		{
			return _next;
		}
		set
		{
			_next = value;
		}
	}

	internal Packet Prev
	{
		get
		{
			return _prev;
		}
		set
		{
			_prev = value;
		}
	}

	internal bool IsContinued
	{
		get
		{
			return GetFlag(PacketFlags.User1);
		}
		set
		{
			SetFlag(PacketFlags.User1, value);
		}
	}

	internal bool IsContinuation
	{
		get
		{
			return GetFlag(PacketFlags.User2);
		}
		set
		{
			SetFlag(PacketFlags.User2, value);
		}
	}

	internal Packet(OggContainerReader containerReader, long streamOffset, int length)
		: base(length)
	{
		_containerReader = containerReader;
		_offset = streamOffset;
		_length = length;
		_curOfs = 0;
	}

	internal void MergeWith(DataPacket continuation)
	{
		if (!(continuation is Packet mergedPacket))
		{
			throw new ArgumentException("Incorrect packet type!");
		}
		base.Length += continuation.Length;
		if (_mergedPacket == null)
		{
			_mergedPacket = mergedPacket;
		}
		else
		{
			_mergedPacket.MergeWith(continuation);
		}
		base.PageGranulePosition = continuation.PageGranulePosition;
		base.PageSequenceNumber = continuation.PageSequenceNumber;
	}

	internal void Reset()
	{
		_curOfs = 0;
		ResetBitReader();
		if (_mergedPacket != null)
		{
			_mergedPacket.Reset();
		}
	}

	protected override int ReadNextByte()
	{
		if (_curOfs == _length)
		{
			if (_mergedPacket == null)
			{
				return -1;
			}
			return _mergedPacket.ReadNextByte();
		}
		int num = _containerReader.PacketReadByte(_offset + _curOfs);
		if (num != -1)
		{
			_curOfs++;
		}
		return num;
	}

	public override void Done()
	{
		if (_mergedPacket != null)
		{
			_mergedPacket.Done();
		}
		else
		{
			_containerReader.PacketDiscardThrough(_offset + _length);
		}
	}
}
[DebuggerTypeProxy(typeof(DebugView))]
internal class PacketReader : IPacketProvider, IDisposable
{
	internal class DebugView
	{
		private PacketReader _reader;

		private Packet _last;

		private Packet _first;

		private Packet[] _packetList = new Packet[0];

		public OggContainerReader Container => _reader._container;

		public int StreamSerial => _reader._streamSerial;

		public bool EndOfStreamFound => _reader._eosFound;

		public int CurrentPacketIndex
		{
			get
			{
				if (_reader._current == null)
				{
					return -1;
				}
				return Array.IndexOf(Packets, _reader._current);
			}
		}

		public Packet[] Packets
		{
			get
			{
				if (_reader._last == _last && _reader._first == _first)
				{
					return _packetList;
				}
				_last = _reader._last;
				_first = _reader._first;
				List<Packet> list = new List<Packet>();
				for (Packet packet = _first; packet != null; packet = packet.Next)
				{
					list.Add(packet);
				}
				_packetList = list.ToArray();
				return _packetList;
			}
		}

		public DebugView(PacketReader reader)
		{
			if (reader == null)
			{
				throw new ArgumentNullException("reader");
			}
			_reader = reader;
		}
	}

	private OggContainerReader _container;

	private int _streamSerial;

	private bool _eosFound;

	private Packet _first;

	private Packet _current;

	private Packet _last;

	private object _packetLock = new object();

	internal bool HasEndOfStream => _eosFound;

	public int StreamSerial => _streamSerial;

	public long ContainerBits { get; set; }

	public bool CanSeek => _container.CanSeek;

	public event EventHandler<ParameterChangeEventArgs> ParameterChange;

	internal PacketReader(OggContainerReader container, int streamSerial)
	{
		_container = container;
		_streamSerial = streamSerial;
	}

	public void Dispose()
	{
		_eosFound = true;
		_container.DisposePacketReader(this);
		_container = null;
		_current = null;
		if (_first != null)
		{
			Packet packet = _first;
			_first = null;
			while (packet.Next != null)
			{
				Packet next = packet.Next;
				packet.Next = null;
				packet = next;
				packet.Prev = null;
			}
			packet = null;
		}
		_last = null;
	}

	internal void AddPacket(Packet packet)
	{
		lock (_packetLock)
		{
			if (_eosFound)
			{
				return;
			}
			if (packet.IsResync)
			{
				packet.IsContinuation = false;
				if (_last != null)
				{
					_last.IsContinued = false;
				}
			}
			if (packet.IsContinuation)
			{
				if (_last == null)
				{
					throw new InvalidDataException();
				}
				if (!_last.IsContinued)
				{
					throw new InvalidDataException();
				}
				_last.MergeWith(packet);
				_last.IsContinued = packet.IsContinued;
			}
			else
			{
				if (packet == null)
				{
					throw new ArgumentException("Wrong packet datatype", "packet");
				}
				if (_first == null)
				{
					_first = packet;
					_last = packet;
				}
				else
				{
					Packet packet2 = (packet.Prev = _last);
					Packet last2 = (packet2.Next = packet);
					_last = last2;
				}
			}
			if (packet.IsEndOfStream)
			{
				SetEndOfStream();
			}
		}
	}

	internal void SetEndOfStream()
	{
		lock (_packetLock)
		{
			_eosFound = true;
			if (_last.IsContinued)
			{
				_last = _last.Prev;
				_last.Next.Prev = null;
				_last.Next = null;
			}
		}
	}

	public DataPacket GetNextPacket()
	{
		return _current = PeekNextPacketInternal();
	}

	public DataPacket PeekNextPacket()
	{
		return PeekNextPacketInternal();
	}

	private Packet PeekNextPacketInternal()
	{
		Packet packet;
		if (_current == null)
		{
			packet = _first;
		}
		else
		{
			while (true)
			{
				lock (_packetLock)
				{
					packet = _current.Next;
					if ((packet != null && !packet.IsContinued) || _eosFound)
					{
						break;
					}
					goto IL_004f;
				}
				IL_004f:
				_container.GatherNextPage(_streamSerial);
			}
		}
		if (packet != null)
		{
			if (packet.IsContinued)
			{
				throw new InvalidDataException("Packet is incomplete!");
			}
			packet.Reset();
		}
		return packet;
	}

	internal void ReadAllPages()
	{
		if (!CanSeek)
		{
			throw new InvalidOperationException();
		}
		while (!_eosFound)
		{
			_container.GatherNextPage(_streamSerial);
		}
	}

	internal DataPacket GetLastPacket()
	{
		ReadAllPages();
		return _last;
	}

	public int GetTotalPageCount()
	{
		ReadAllPages();
		int num = 0;
		int num2 = 0;
		for (Packet packet = _first; packet != null; packet = packet.Next)
		{
			if (packet.PageSequenceNumber != num2)
			{
				num++;
				num2 = packet.PageSequenceNumber;
			}
		}
		return num;
	}

	public DataPacket GetPacket(int packetIndex)
	{
		if (!CanSeek)
		{
			throw new InvalidOperationException();
		}
		if (packetIndex < 0)
		{
			throw new ArgumentOutOfRangeException("index");
		}
		if (_first == null)
		{
			throw new InvalidOperationException("Packet reader has no packets!");
		}
		Packet packet = _first;
		while (--packetIndex >= 0)
		{
			while (packet.Next == null)
			{
				if (_eosFound)
				{
					throw new ArgumentOutOfRangeException("index");
				}
				_container.GatherNextPage(_streamSerial);
			}
			packet = packet.Next;
		}
		packet.Reset();
		return packet;
	}

	private Packet GetLastPacketInPage(Packet packet)
	{
		if (packet != null)
		{
			int pageSequenceNumber = packet.PageSequenceNumber;
			while (packet.Next != null && packet.Next.PageSequenceNumber == pageSequenceNumber)
			{
				packet = packet.Next;
			}
			if (packet != null && packet.IsContinued)
			{
				packet = packet.Prev;
			}
		}
		return packet;
	}

	private Packet FindPacketInPage(Packet pagePacket, long targetGranulePos, Func<DataPacket, DataPacket, int> packetGranuleCountCallback)
	{
		Packet lastPacketInPage = GetLastPacketInPage(pagePacket);
		if (lastPacketInPage == null)
		{
			return null;
		}
		Packet packet = lastPacketInPage;
		do
		{
			if (!packet.GranuleCount.HasValue)
			{
				if (packet == lastPacketInPage)
				{
					packet.GranulePosition = packet.PageGranulePosition;
				}
				else
				{
					packet.GranulePosition = packet.Next.GranulePosition - packet.Next.GranuleCount.Value;
				}
				if (packet == _last && _eosFound && packet.Prev.PageSequenceNumber < packet.PageSequenceNumber)
				{
					packet.GranuleCount = (int)(packet.GranulePosition - packet.Prev.PageGranulePosition);
				}
				else if (packet.Prev != null)
				{
					packet.Prev.Reset();
					packet.Reset();
					packet.GranuleCount = packetGranuleCountCallback(packet, packet.Prev);
				}
				else
				{
					if (packet.GranulePosition > packet.Next.GranulePosition - packet.Next.GranuleCount)
					{
						throw new InvalidOperationException("First data packet size mismatch");
					}
					packet.GranuleCount = (int)packet.GranulePosition;
				}
			}
			if (targetGranulePos <= packet.GranulePosition && targetGranulePos > packet.GranulePosition - packet.GranuleCount)
			{
				if (packet.Prev != null && !packet.Prev.GranuleCount.HasValue)
				{
					packet.Prev.GranulePosition = packet.GranulePosition - packet.GranuleCount.Value;
				}
				return packet;
			}
			packet = packet.Prev;
		}
		while (packet != null && packet.PageSequenceNumber == lastPacketInPage.PageSequenceNumber);
		if (packet != null && packet.PageGranulePosition < targetGranulePos)
		{
			packet.GranulePosition = packet.PageGranulePosition;
			return packet.Next;
		}
		return null;
	}

	public DataPacket FindPacket(long granulePos, Func<DataPacket, DataPacket, int> packetGranuleCountCallback)
	{
		if (granulePos < 0)
		{
			throw new ArgumentOutOfRangeException("granulePos");
		}
		Packet packet = null;
		Packet packet2 = _current ?? _first;
		if (granulePos > packet2.PageGranulePosition)
		{
			while (granulePos > packet2.PageGranulePosition)
			{
				if ((packet2.Next == null || packet2.IsContinued) && !_eosFound)
				{
					_container.GatherNextPage(_streamSerial);
					if (_eosFound)
					{
						packet2 = null;
						break;
					}
				}
				packet2 = packet2.Next;
			}
			return FindPacketInPage(packet2, granulePos, packetGranuleCountCallback);
		}
		while (packet2.Prev != null && (granulePos <= packet2.Prev.PageGranulePosition || packet2.Prev.PageGranulePosition == -1))
		{
			packet2 = packet2.Prev;
		}
		return FindPacketInPage(packet2, granulePos, packetGranuleCountCallback);
	}

	public void SeekToPacket(DataPacket packet, int preRoll)
	{
		if (preRoll < 0)
		{
			throw new ArgumentOutOfRangeException("preRoll");
		}
		if (packet == null)
		{
			throw new ArgumentNullException("granulePos");
		}
		Packet packet2 = packet as Packet;
		if (packet2 == null)
		{
			throw new ArgumentException("Incorrect packet type!", "packet");
		}
		while (--preRoll >= 0)
		{
			packet2 = packet2.Prev;
			if (packet2 == null)
			{
				throw new ArgumentOutOfRangeException("preRoll");
			}
		}
		_current = packet2.Prev;
	}

	public long GetGranuleCount()
	{
		return GetLastPacket().PageGranulePosition;
	}
}
[Flags]
internal enum PageFlags
{
	None = 0,
	ContinuesPacket = 1,
	BeginningOfStream = 2,
	EndOfStream = 4
}
internal class OpusHeader
{
	private byte version;

	private byte channel_count;

	private ushort pre_skip;

	private uint input_sample_rate;

	private short output_gain;

	private byte mapping_family;

	private byte stream_count;

	private byte coupled_count;
}
public class OpusOggReadStream
{
	private const double GranuleSampleRate = 48000.0;

	private readonly Stream _stream;

	private readonly IOpusDecoder _decoder;

	private byte[] _nextDataPacket;

	private IPacketProvider _packetProvider;

	private bool _endOfStream;

	public bool CanSeek => _stream.CanSeek;

	public OpusTags Tags { get; private set; }

	public bool HasNextPacket => !_endOfStream;

	public string LastError { get; private set; }

	public long PageGranulePosition { get; private set; }

	public TimeSpan CurrentTime => TimeSpan.FromSeconds((double)PageGranulePosition / 48000.0);

	public long GranuleCount { get; private set; }

	public TimeSpan TotalTime => TimeSpan.FromSeconds((double)GranuleCount / 48000.0);

	public long PagePosition { get; private set; }

	public long PageCount { get; private set; }

	public OpusOggReadStream(IOpusDecoder decoder, Stream stream)
	{
		if (stream == null)
		{
			throw new ArgumentNullException("stream");
		}
		_stream = stream;
		_decoder = decoder;
		_endOfStream = !Initialize();
	}

	public short[] DecodeNextPacket()
	{
		//IL_0091: Expected O, but got Unknown
		if (_decoder == null)
		{
			throw new InvalidOperationException("Cannot decode opus packets as a decoder was never provided");
		}
		if (_nextDataPacket == null || _nextDataPacket.Length == 0)
		{
			_endOfStream = true;
			return null;
		}
		try
		{
			int numSamples = OpusPacketInfo.GetNumSamples((ReadOnlySpan<byte>)_nextDataPacket.AsSpan(), _decoder.SampleRate);
			short[] array = new short[numSamples * _decoder.NumChannels];
			_decoder.Decode((ReadOnlySpan<byte>)_nextDataPacket.AsSpan(), array.AsSpan(), numSamples, false);
			QueueNextPacket();
			return array;
		}
		catch (OpusException val)
		{
			OpusException val2 = val;
			LastError = "Opus decoder threw exception: " + ((Exception)(object)val2).Message;
			return null;
		}
	}

	public byte[] ReadNextRawPacket()
	{
		if (_nextDataPacket == null || _nextDataPacket.Length == 0)
		{
			_endOfStream = true;
			return null;
		}
		byte[] nextDataPacket = _nextDataPacket;
		QueueNextPacket();
		return nextDataPacket;
	}

	private bool Initialize()
	{
		try
		{
			OggContainerReader oggContainerReader = new OggContainerReader(_stream, closeOnDispose: true);
			if (!oggContainerReader.Init())
			{
				LastError = "Could not initialize stream";
				return false;
			}
			if (oggContainerReader.StreamSerials.Length == 0)
			{
				LastError = "Initialization failed: No elementary streams found in input file";
				return false;
			}
			int streamSerial = oggContainerReader.StreamSerials[0];
			_packetProvider = oggContainerReader.GetStream(streamSerial);
			if (CanSeek)
			{
				GranuleCount = _packetProvider.GetGranuleCount();
				PageCount = _packetProvider.GetTotalPageCount();
			}
			QueueNextPacket();
			return true;
		}
		catch (Exception ex)
		{
			LastError = "Unknown initialization error: " + ex.Message;
			return false;
		}
	}

	public void SeekTo(TimeSpan playbackTime)
	{
		if (!CanSeek)
		{
			throw new InvalidOperationException("Stream is not seekable.");
		}
		if (playbackTime < TimeSpan.Zero || playbackTime > TotalTime)
		{
			throw new ArgumentOutOfRangeException("playbackTime");
		}
		long granulePosition = Convert.ToInt64(playbackTime.TotalSeconds * 48000.0);
		SeekToGranulePosition(granulePosition);
	}

	private void SeekToGranulePosition(long granulePosition)
	{
		if (!CanSeek)
		{
			throw new InvalidOperationException("Stream is not seekable.");
		}
		if (granulePosition < 0 || granulePosition > GranuleCount)
		{
			throw new ArgumentOutOfRangeException("granulePosition");
		}
		DataPacket dataPacket = _packetProvider.FindPacket(granulePosition, GetPacketLength);
		if (dataPacket == null || dataPacket.IsEndOfStream)
		{
			_endOfStream = true;
			_nextDataPacket = null;
			return;
		}
		_packetProvider.SeekToPacket(dataPacket, 1);
		PageGranulePosition = _packetProvider.PeekNextPacket().PageGranulePosition;
		if (_decoder != null)
		{
			_decoder.ResetState();
		}
	}

	private int GetPacketLength(DataPacket curPacket, DataPacket lastPacket)
	{
		if (lastPacket == null || curPacket.IsResync)
		{
			return 0;
		}
		if (curPacket.ReadBit())
		{
			return 0;
		}
		if (lastPacket.ReadBit())
		{
			return 0;
		}
		return 1;
	}

	private void QueueNextPacket()
	{
		if (_endOfStream)
		{
			return;
		}
		DataPacket nextPacket = _packetProvider.GetNextPacket();
		if (nextPacket == null)
		{
			_endOfStream = true;
			_nextDataPacket = null;
			return;
		}
		PageGranulePosition = nextPacket.PageGranulePosition;
		PagePosition = nextPacket.PageSequenceNumber;
		byte[] array = new byte[nextPacket.Length];
		nextPacket.Read(array, 0, nextPacket.Length);
		nextPacket.Done();
		if (array.Length > 8 && "OpusHead".Equals(Encoding.UTF8.GetString(array, 0, 8)))
		{
			QueueNextPacket();
		}
		else if (array.Length > 8 && "OpusTags".Equals(Encoding.UTF8.GetString(array, 0, 8)))
		{
			Tags = OpusTags.ParsePacket(array, array.Length);
			QueueNextPacket();
		}
		else
		{
			_nextDataPacket = array;
		}
	}
}
public class OpusOggWriteStream
{
	private const int FRAME_SIZE_MS = 20;

	private IOpusEncoder _encoder;

	private Stream _outputStream;

	private Crc _crc;

	private int _inputChannels;

	private IResampler _resampler;

	private int _inputSampleRate;

	private readonly bool _leaveOpen;

	private int _encoderSampleRate;

	private short[] _opusFrame;

	private int _opusFrameSamples;

	private int _opusFrameIndex;

	private byte[] _currentHeader = new byte[400];

	private byte[] _currentPayload = new byte[65536];

	private int _headerIndex;

	private int _payloadIndex;

	private int _pageCounter;

	private int _logicalStreamId;

	private long _granulePosition;

	private byte _lacingTableCount;

	private const int PAGE_FLAGS_POS = 5;

	private const int GRANULE_COUNT_POS = 6;

	private const int CHECKSUM_HEADER_POS = 22;

	private const int SEGMENT_COUNT_POS = 26;

	private bool _finalized;

	public OpusOggWriteStream(IOpusEncoder encoder, Stream outputStream, OpusTags fileTags = null, int inputSampleRate = 0, int resamplerQuality = 5, bool leaveOpen = false)
	{
		_encoder = encoder;
		if (_encoder.UseDTX)
		{
			throw new ArgumentException("DTX is not currently supported in Ogg streams");
		}
		_inputSampleRate = inputSampleRate;
		_leaveOpen = leaveOpen;
		if (_inputSampleRate == 0)
		{
			_inputSampleRate = _encoder.SampleRate;
		}
		_logicalStreamId = new Random().Next();
		_encoderSampleRate = encoder.SampleRate;
		_inputChannels = encoder.NumChannels;
		_outputStream = outputStream;
		_opusFrameIndex = 0;
		_granulePosition = 0L;
		_opusFrameSamples = (int)((long)_encoderSampleRate * 20L / 1000);
		_opusFrame = new short[_opusFrameSamples * _inputChannels];
		_crc = new Crc();
		_resampler = ResamplerFactory.CreateResampler(_inputChannels, _inputSampleRate, _encoderSampleRate, resamplerQuality, (TextWriter)null);
		BeginNewPage();
		WriteOpusHeadPage();
		WriteOpusTagsPage(fileTags);
	}

	public void WriteSamples(short[] data, int offset, int count)
	{
		if (_finalized)
		{
			throw new InvalidOperationException("Cannot write new samples to Ogg file, the output stream is already closed!");
		}
		if (data.Length - offset < count)
		{
			throw new ArgumentOutOfRangeException("The given audio buffer claims to have " + count + " samples, but it actually only has " + (data.Length - offset));
		}
		int num = 0;
		for (int num2 = Math.Min(_opusFrame.Length - _opusFrameIndex, count - num); num2 > 0; num2 = Math.Min(_opusFrame.Length - _opusFrameIndex, count - num))
		{
			if (_inputSampleRate != _encoderSampleRate)
			{
				int num3 = (count - num) / _inputChannels;
				int num4 = num2 / _inputChannels;
				_resampler.ProcessInterleaved(data.AsSpan(offset + num), ref num3, _opusFrame.AsSpan(_opusFrameIndex), ref num4);
				num += num3 * _inputChannels;
				_opusFrameIndex += num4 * _inputChannels;
			}
			else
			{
				data.AsSpan(offset + num, num2).CopyTo(_opusFrame.AsSpan(_opusFrameIndex, num2));
				_opusFrameIndex += num2;
				num += num2;
			}
			if (_opusFrameIndex == _opusFrame.Length)
			{
				int num5 = _encoder.Encode((ReadOnlySpan<short>)_opusFrame.AsSpan(), _opusFrameSamples, _currentPayload.AsSpan(_payloadIndex), _currentPayload.Length - _payloadIndex);
				_payloadIndex += num5;
				_granulePosition += 960L;
				int num6 = num5;
				while (num6 >= 255)
				{
					num6 -= 255;
					_currentHeader[_headerIndex++] = byte.MaxValue;
					_lacingTableCount++;
				}
				_currentHeader[_headerIndex++] = (byte)num6;
				_lacingTableCount++;
				if (_lacingTableCount > 248)
				{
					FinalizePage();
				}
				_opusFrameIndex = 0;
			}
		}
	}

	public void WriteSamples(float[] data, int offset, int count)
	{
		if (_finalized)
		{
			throw new InvalidOperationException("Cannot write new samples to Ogg file, the output stream is already closed!");
		}
		short[] array = new short[count];
		for (int i = 0; i < count; i++)
		{
			array[i] = (short)(data[i + offset] * 32767f);
		}
		WriteSamples(array, 0, count);
	}

	public void Finish()
	{
		int num = _opusFrame.Length - _opusFrameIndex;
		short[] data = new short[num];
		WriteSamples(data, 0, num);
		FinalizePage();
		WriteStreamFinishedPage();
		_outputStream.Flush();
		if (!_leaveOpen)
		{
			_outputStream.Dispose();
		}
		_finalized = true;
	}

	private void WriteStreamFinishedPage()
	{
		_currentHeader[_headerIndex++] = 0;
		_lacingTableCount++;
		_currentHeader[5] = 4;
		FinalizePage();
	}

	private void WriteOpusHeadPage()
	{
		if (_payloadIndex != 0)
		{
			throw new InvalidOperationException("Must begin writing OpusHead on a new page!");
		}
		_payloadIndex += WriteValueToByteBuffer("OpusHead", _currentPayload, _payloadIndex);
		_currentPayload[_payloadIndex++] = 1;
		_currentPayload[_payloadIndex++] = (byte)_inputChannels;
		short val = 0;
		_payloadIndex += WriteValueToByteBuffer(val, _currentPayload, _payloadIndex);
		_payloadIndex += WriteValueToByteBuffer(_encoderSampleRate, _currentPayload, _payloadIndex);
		short val2 = 0;
		_payloadIndex += WriteValueToByteBuffer(val2, _currentPayload, _payloadIndex);
		_currentPayload[_payloadIndex++] = 0;
		_currentHeader[_headerIndex++] = (byte)_payloadIndex;
		_lacingTableCount++;
		_currentHeader[5] = 2;
		FinalizePage();
	}

	private void WriteOpusTagsPage(OpusTags tags = null)
	{
		if (tags == null)
		{
			tags = new OpusTags();
		}
		if (string.IsNullOrEmpty(tags.Comment))
		{
			tags.Comment = _encoder.GetVersionString();
		}
		if (_payloadIndex != 0)
		{
			throw new InvalidOperationException("Must begin writing OpusTags on a new page!");
		}
		_payloadIndex += WriteValueToByteBuffer("OpusTags", _currentPayload, _payloadIndex);
		int num = WriteValueToByteBuffer(tags.Comment, _currentPayload, _payloadIndex + 4);
		_payloadIndex += WriteValueToByteBuffer(num, _currentPayload, _payloadIndex);
		_payloadIndex += num;
		int payloadIndex = _payloadIndex;
		_payloadIndex += 4;
		int num2 = 0;
		foreach (KeyValuePair<string, string> field in tags.Fields)
		{
			if (!string.IsNullOrEmpty(field.Key) && !string.IsNullOrEmpty(field.Value))
			{
				num = WriteValueToByteBuffer(field.Key + "=" + field.Value, _currentPayload, _payloadIndex + 4);
				_payloadIndex += WriteValueToByteBuffer(num, _currentPayload, _payloadIndex);
				_payloadIndex += num;
				num2++;
			}
		}
		WriteValueToByteBuffer(num2, _currentPayload, payloadIndex);
		int num3;
		for (num3 = _payloadIndex; num3 >= 255; num3 -= 255)
		{
			_currentHeader[_headerIndex++] = byte.MaxValue;
			_lacingTableCount++;
		}
		_currentHeader[_headerIndex++] = (byte)num3;
		_lacingTableCount++;
		FinalizePage();
	}

	private void BeginNewPage()
	{
		_headerIndex = 0;
		_payloadIndex = 0;
		_lacingTableCount = 0;
		_headerIndex += WriteValueToByteBuffer("OggS", _currentHeader, _headerIndex);
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_headerIndex += WriteValueToByteBuffer(_granulePosition, _currentHeader, _headerIndex);
		_headerIndex += WriteValueToByteBuffer(_logicalStreamId, _currentHeader, _headerIndex);
		_headerIndex += WriteValueToByteBuffer(_pageCounter, _currentHeader, _headerIndex);
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = _lacingTableCount;
		_pageCounter++;
	}

	private void FinalizePage()
	{
		if (_finalized)
		{
			throw new InvalidOperationException("Cannot finalize page, the output stream is already closed!");
		}
		if (_lacingTableCount != 0)
		{
			_currentHeader[26] = _lacingTableCount;
			WriteValueToByteBuffer(_granulePosition, _currentHeader, 6);
			_crc.Reset();
			for (int i = 0; i < _headerIndex; i++)
			{
				_crc.Update(_currentHeader[i]);
			}
			for (int j = 0; j < _payloadIndex; j++)
			{
				_crc.Update(_currentPayload[j]);
			}
			WriteValueToByteBuffer(_crc.Value, _currentHeader, 22);
			_outputStream.Write(_currentHeader, 0, _headerIndex);
			_outputStream.Write(_currentPayload, 0, _payloadIndex);
			BeginNewPage();
		}
	}

	private static int WriteValueToByteBuffer(int val, byte[] target, int targetOffset)
	{
		BinaryHelpers.Int32ToByteArrayLittleEndian(val, target, targetOffset);
		return 4;
	}

	private static int WriteValueToByteBuffer(long val, byte[] target, int targetOffset)
	{
		BinaryHelpers.Int64ToByteArrayLittleEndian(val, target, targetOffset);
		return 8;
	}

	private static int WriteValueToByteBuffer(uint val, byte[] target, int targetOffset)
	{
		BinaryHelpers.UInt32ToByteArrayLittleEndian(val, target, targetOffset);
		return 4;
	}

	private static int WriteValueToByteBuffer(short val, byte[] target, int targetOffset)
	{
		BinaryHelpers.Int16ToByteArrayLittleEndian(val, target, targetOffset);
		return 2;
	}

	private static int WriteValueToByteBuffer(string val, byte[] target, int targetOffset)
	{
		if (string.IsNullOrEmpty(val))
		{
			return 0;
		}
		return Encoding.UTF8.GetBytes(val, 0, val.Length, target, targetOffset);
	}
}
public class OpusRawWriteStream
{
	private Stream _outputStream;

	private Crc _crc;

	private int _inputChannels;

	private readonly bool _leaveOpen;

	private int _inputSampleRate;

	private byte[] _currentHeader = new byte[400];

	private byte[] _currentPayload = new byte[65536];

	private int _headerIndex;

	private int _payloadIndex;

	private int _pageCounter;

	private int _logicalStreamId;

	private long _granulePosition;

	private byte _lacingTableCount;

	private const int PAGE_FLAGS_POS = 5;

	private const int GRANULE_COUNT_POS = 6;

	private const int CHECKSUM_HEADER_POS = 22;

	private const int SEGMENT_COUNT_POS = 26;

	private bool _finalized;

	public OpusRawWriteStream(Stream outputStream, OpusTags fileTags, int inputSampleRate, int inputNumChannels, bool leaveOpen = false)
	{
		_inputSampleRate = inputSampleRate;
		_logicalStreamId = new Random().Next();
		_inputChannels = inputNumChannels;
		_leaveOpen = leaveOpen;
		_outputStream = outputStream;
		_granulePosition = 0L;
		_crc = new Crc();
		BeginNewPage();
		WriteOpusHeadPage();
		WriteOpusTagsPage(fileTags);
	}

	public void WriteSinglePacket(byte[] opusPacket, int offset, int packetSize)
	{
		if (_finalized)
		{
			throw new InvalidOperationException("Cannot write new samples to Ogg file, the output stream is already closed!");
		}
		if (opusPacket.Length - offset < packetSize)
		{
			throw new ArgumentOutOfRangeException("The given audio buffer claims to have " + packetSize + " samples, but it actually only has " + (opusPacket.Length - offset));
		}
		Array.Copy(opusPacket, offset, _currentPayload, _payloadIndex, packetSize);
		_payloadIndex += packetSize;
		int numSamplesPerFrame = OpusPacketInfo.GetNumSamplesPerFrame((ReadOnlySpan<byte>)opusPacket.AsSpan(offset), 48000);
		_granulePosition += numSamplesPerFrame;
		int num = packetSize;
		while (num >= 255)
		{
			num -= 255;
			_currentHeader[_headerIndex++] = byte.MaxValue;
			_lacingTableCount++;
		}
		_currentHeader[_headerIndex++] = (byte)num;
		_lacingTableCount++;
		if (_lacingTableCount > 248)
		{
			FinalizePage();
		}
	}

	public void Finish()
	{
		FinalizePage();
		WriteStreamFinishedPage();
		_outputStream.Flush();
		if (!_leaveOpen)
		{
			_outputStream.Dispose();
		}
		_finalized = true;
	}

	private void WriteStreamFinishedPage()
	{
		_currentHeader[_headerIndex++] = 0;
		_lacingTableCount++;
		_currentHeader[5] = 4;
		FinalizePage();
	}

	private void WriteOpusHeadPage()
	{
		if (_payloadIndex != 0)
		{
			throw new InvalidOperationException("Must begin writing OpusHead on a new page!");
		}
		_payloadIndex += WriteValueToByteBuffer("OpusHead", _currentPayload, _payloadIndex);
		_currentPayload[_payloadIndex++] = 1;
		_currentPayload[_payloadIndex++] = (byte)_inputChannels;
		short val = 0;
		_payloadIndex += WriteValueToByteBuffer(val, _currentPayload, _payloadIndex);
		_payloadIndex += WriteValueToByteBuffer(_inputSampleRate, _currentPayload, _payloadIndex);
		short val2 = 0;
		_payloadIndex += WriteValueToByteBuffer(val2, _currentPayload, _payloadIndex);
		_currentPayload[_payloadIndex++] = 0;
		_currentHeader[_headerIndex++] = (byte)_payloadIndex;
		_lacingTableCount++;
		_currentHeader[5] = 2;
		FinalizePage();
	}

	private void WriteOpusTagsPage(OpusTags tags = null)
	{
		if (tags == null)
		{
			tags = new OpusTags();
		}
		if (string.IsNullOrEmpty(tags.Comment))
		{
			tags.Comment = "Concentus.OggFile";
		}
		if (_payloadIndex != 0)
		{
			throw new InvalidOperationException("Must begin writing OpusTags on a new page!");
		}
		_payloadIndex += WriteValueToByteBuffer("OpusTags", _currentPayload, _payloadIndex);
		int num = WriteValueToByteBuffer(tags.Comment, _currentPayload, _payloadIndex + 4);
		_payloadIndex += WriteValueToByteBuffer(num, _currentPayload, _payloadIndex);
		_payloadIndex += num;
		int payloadIndex = _payloadIndex;
		_payloadIndex += 4;
		int num2 = 0;
		foreach (KeyValuePair<string, string> field in tags.Fields)
		{
			if (!string.IsNullOrEmpty(field.Key) && !string.IsNullOrEmpty(field.Value))
			{
				num = WriteValueToByteBuffer(field.Key + "=" + field.Value, _currentPayload, _payloadIndex + 4);
				_payloadIndex += WriteValueToByteBuffer(num, _currentPayload, _payloadIndex);
				_payloadIndex += num;
				num2++;
			}
		}
		WriteValueToByteBuffer(num2, _currentPayload, payloadIndex);
		int num3;
		for (num3 = _payloadIndex; num3 >= 255; num3 -= 255)
		{
			_currentHeader[_headerIndex++] = byte.MaxValue;
			_lacingTableCount++;
		}
		_currentHeader[_headerIndex++] = (byte)num3;
		_lacingTableCount++;
		FinalizePage();
	}

	private void BeginNewPage()
	{
		_headerIndex = 0;
		_payloadIndex = 0;
		_lacingTableCount = 0;
		_headerIndex += WriteValueToByteBuffer("OggS", _currentHeader, _headerIndex);
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_headerIndex += WriteValueToByteBuffer(_granulePosition, _currentHeader, _headerIndex);
		_headerIndex += WriteValueToByteBuffer(_logicalStreamId, _currentHeader, _headerIndex);
		_headerIndex += WriteValueToByteBuffer(_pageCounter, _currentHeader, _headerIndex);
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = 0;
		_currentHeader[_headerIndex++] = _lacingTableCount;
		_pageCounter++;
	}

	private void FinalizePage()
	{
		if (_finalized)
		{
			throw new InvalidOperationException("Cannot finalize page, the output stream is already closed!");
		}
		if (_lacingTableCount != 0)
		{
			_currentHeader[26] = _lacingTableCount;
			WriteValueToByteBuffer(_granulePosition, _currentHeader, 6);
			_crc.Reset();
			for (int i = 0; i < _headerIndex; i++)
			{
				_crc.Update(_currentHeader[i]);
			}
			for (int j = 0; j < _payloadIndex; j++)
			{
				_crc.Update(_currentPayload[j]);
			}
			WriteValueToByteBuffer(_crc.Value, _currentHeader, 22);
			_outputStream.Write(_currentHeader, 0, _headerIndex);
			_outputStream.Write(_currentPayload, 0, _payloadIndex);
			BeginNewPage();
		}
	}

	private static int WriteValueToByteBuffer(int val, byte[] target, int targetOffset)
	{
		Array.Copy(BitConverter.GetBytes(val), 0, target, targetOffset, 4);
		return 4;
	}

	private static int WriteValueToByteBuffer(long val, byte[] target, int targetOffset)
	{
		Array.Copy(BitConverter.GetBytes(val), 0, target, targetOffset, 8);
		return 8;
	}

	private static int WriteValueToByteBuffer(uint val, byte[] target, int targetOffset)
	{
		Array.Copy(BitConverter.GetBytes(val), 0, target, targetOffset, 4);
		return 4;
	}

	private static int WriteValueToByteBuffer(short val, byte[] target, int targetOffset)
	{
		Array.Copy(BitConverter.GetBytes(val), 0, target, targetOffset, 2);
		return 2;
	}

	private static int WriteValueToByteBuffer(string val, byte[] target, int targetOffset)
	{
		if (string.IsNullOrEmpty(val))
		{
			return 0;
		}
		byte[] bytes = Encoding.UTF8.GetBytes(val);
		Array.Copy(bytes, 0, target, targetOffset, bytes.Length);
		return bytes.Length;
	}
}
public class OpusTagName
{
	public const string Title = "title";

	public const string Artist = "artist";

	public const string Album = "album";
}
public class OpusTags
{
	private string _comment = string.Empty;

	private IDictionary<string, string> _fields = new Dictionary<string, string>();

	public string Comment
	{
		get
		{
			return _comment;
		}
		set
		{
			_comment = value;
		}
	}

	public IDictionary<string, string> Fields => _fields;

	internal static OpusTags ParsePacket(byte[] packet, int packetLength)
	{
		if (packetLength < 8)
		{
			return null;
		}
		if (!"OpusTags".Equals(Encoding.UTF8.GetString(packet, 0, 8)))
		{
			return null;
		}
		OpusTags opusTags = new OpusTags();
		int num = 8;
		int num2 = BitConverter.ToInt32(packet, num);
		num += 4;
		if (num2 > 0)
		{
			opusTags._comment = Encoding.UTF8.GetString(packet, num, num2);
			num += num2;
		}
		int num3 = BitConverter.ToInt32(packet, num);
		num += 4;
		for (int i = 0; i < num3; i++)
		{
			num2 = BitConverter.ToInt32(packet, num);
			num += 4;
			if (num2 > 0)
			{
				string @string = Encoding.UTF8.GetString(packet, num, num2);
				num += num2;
				int num4 = @string.IndexOf('=');
				if (num4 > 0)
				{
					string key = @string.Substring(0, num4);
					string value = @string.Substring(num4 + 1);
					opusTags._fields[key] = value;
				}
			}
		}
		return opusTags;
	}
}
internal class ParameterChangeEventArgs : EventArgs
{
	public DataPacket FirstPacket { get; private set; }

	public ParameterChangeEventArgs(DataPacket firstPacket)
	{
		FirstPacket = firstPacket;
	}
}
internal class StreamReadBuffer : IDisposable
{
	internal class StreamWrapper
	{
		internal Stream Source;

		internal object LockObject = new object();

		internal long EofOffset = long.MaxValue;

		internal int RefCount = 1;
	}

	private class SavedBuffer
	{
		public byte[] Buffer;

		public long BaseOffset;

		public int End;

		public int DiscardCount;

		public long VersionSaved;
	}

	private static Dictionary<Stream, StreamWrapper> _lockObjects = new Dictionary<Stream, StreamWrapper>();

	private StreamWrapper _wrapper;

	private int _maxSize;

	private byte[] _data;

	private long _baseOffset;

	private int _end;

	private int _discardCount;

	private bool _minimalRead;

	private long _versionCounter;

	private List<SavedBuffer> _savedBuffers;

	public bool MinimalRead
	{
		get
		{
			return _minimalRead;
		}
		set
		{
			_minimalRead = value;
		}
	}

	public int MaxSize
	{
		get
		{
			return _maxSize;
		}
		set
		{
			if (value < 1)
			{
				throw new ArgumentOutOfRangeException("Must be greater than zero.");
			}
			int num = 1 << (int)Math.Ceiling(Math.Log(value, 2.0));
			if (num < _end)
			{
				if (num < _end - _discardCount)
				{
					throw new ArgumentOutOfRangeException("Must be greater than or equal to the number of bytes currently buffered.");
				}
				CommitDiscard();
				byte[] array = new byte[num];
				Buffer.BlockCopy(_data, 0, array, 0, _end);
				_data = array;
			}
			_maxSize = num;
		}
	}

	public long BaseOffset => _baseOffset + _discardCount;

	public int BytesFilled => _end - _discardCount;

	public int Length => _data.Length;

	internal long BufferEndOffset
	{
		get
		{
			if (_end - _discardCount > 0)
			{
				return _baseOffset + _discardCount + _maxSize;
			}
			if (_wrapper.Source.CanSeek)
			{
				return _wrapper.Source.Length;
			}
			return _baseOffset + Length;
		}
	}

	internal StreamReadBuffer(Stream source, int initialSize, int maxSize, bool minimalRead)
	{
		StreamWrapper value;
		lock (_lockObjects)
		{
			if (!_lockObjects.TryGetValue(source, out value))
			{
				_lockObjects.Add(source, new StreamWrapper
				{
					Source = source
				});
				value = _lockObjects[source];
				if (source.CanSeek)
				{
					value.EofOffset = source.Length;
				}
			}
			else
			{
				value.RefCount++;
			}
		}
		initialSize = 2 << (int)Math.Log(initialSize - 1, 2.0);
		maxSize = 1 << (int)Math.Log(maxSize, 2.0);
		_wrapper = value;
		_data = new byte[initialSize];
		_maxSize = maxSize;
		_minimalRead = minimalRead;
		_savedBuffers = new List<SavedBuffer>();
	}

	public void Dispose()
	{
		lock (_lockObjects)
		{
			if (--_wrapper.RefCount == 0)
			{
				_lockObjects.Remove(_wrapper.Source);
			}
		}
	}

	public int Read(long offset, byte[] buffer, int index, int count)
	{
		if (offset < 0)
		{
			throw new ArgumentOutOfRangeException("offset");
		}
		if (buffer == null)
		{
			throw new ArgumentNullException("buffer");
		}
		if (index < 0 || index + count > buffer.Length)
		{
			throw new ArgumentOutOfRangeException("index");
		}
		if (count < 0)
		{
			throw new ArgumentOutOfRangeException("count");
		}
		if (offset >= _wrapper.EofOffset)
		{
			return 0;
		}
		int srcOffset = EnsureAvailable(offset, ref count, isRecursion: false);
		Buffer.BlockCopy(_data, srcOffset, buffer, index, count);
		return count;
	}

	internal int ReadByte(long offset)
	{
		if (offset < 0)
		{
			throw new ArgumentOutOfRangeException("offset");
		}
		if (offset >= _wrapper.EofOffset)
		{
			return -1;
		}
		int count = 1;
		int num = EnsureAvailable(offset, ref count, isRecursion: false);
		if (count == 1)
		{
			return _data[num];
		}
		return -1;
	}

	private int EnsureAvailable(long offset, ref int count, bool isRecursion)
	{
		if (offset >= _baseOffset && offset + count < _baseOffset + _end)
		{
			return (int)(offset - _baseOffset);
		}
		if (count > _maxSize)
		{
			throw new InvalidOperationException("Not enough room in the buffer!  Increase the maximum size and try again.");
		}
		_versionCounter++;
		if (!isRecursion)
		{
			for (int i = 0; i < _savedBuffers.Count; i++)
			{
				long num = _savedBuffers[i].BaseOffset - offset;
				if ((num < 0 && _savedBuffers[i].End + num > 0) || (num > 0 && count - num > 0))
				{
					SwapBuffers(_savedBuffers[i]);
					return EnsureAvailable(offset, ref count, isRecursion: true);
				}
			}
		}
		while (_savedBuffers.Count > 0 && _savedBuffers[0].VersionSaved + 25 < _versionCounter)
		{
			_savedBuffers[0].Buffer = null;
			_savedBuffers.RemoveAt(0);
		}
		if (offset < _baseOffset && !_wrapper.Source.CanSeek)
		{
			throw new InvalidOperationException("Cannot seek before buffer on forward-only streams!");
		}
		CalcBuffer(offset, count, out var readStart, out var readEnd);
		count = FillBuffer(offset, count, readStart, readEnd);
		return (int)(offset - _baseOffset);
	}

	private void SaveBuffer()
	{
		_savedBuffers.Add(new SavedBuffer
		{
			Buffer = _data,
			BaseOffset = _baseOffset,
			End = _end,
			DiscardCount = _discardCount,
			VersionSaved = _versionCounter
		});
		_data = null;
		_end = 0;
		_discardCount = 0;
	}

	private void CreateNewBuffer(long offset, int count)
	{
		SaveBuffer();
		_data = new byte[Math.Min(2 << (int)Math.Log(count - 1, 2.0), _maxSize)];
		_baseOffset = offset;
	}

	private void SwapBuffers(SavedBuffer savedBuffer)
	{
		_savedBuffers.Remove(savedBuffer);
		SaveBuffer();
		_data = savedBuffer.Buffer;
		_baseOffset = savedBuffer.BaseOffset;
		_end = savedBuffer.End;
		_discardCount = savedBuffer.DiscardCount;
	}

	private void CalcBuffer(long offset, int count, out int readStart, out int readEnd)
	{
		readStart = 0;
		readEnd = 0;
		if (offset < _baseOffset)
		{
			if (offset + _maxSize <= _baseOffset)
			{
				if (_baseOffset - (offset + _maxSize) > _maxSize)
				{
					CreateNewBuffer(offset, count);
				}
				else
				{
					EnsureBufferSize(count, copyContents: false, 0);
				}
				_baseOffset = offset;
				readEnd = count;
			}
			else
			{
				readEnd = (int)(offset - _baseOffset);
				EnsureBufferSize(Math.Min((int)(offset + _maxSize - _baseOffset), _end) - readEnd, copyContents: true, readEnd);
				readEnd = (int)(offset - _baseOffset) - readEnd;
			}
		}
		else if (offset >= _baseOffset + _maxSize)
		{
			if (offset - (_baseOffset + _maxSize) > _maxSize)
			{
				CreateNewBuffer(offset, count);
			}
			else
			{
				EnsureBufferSize(count, copyContents: false, 0);
			}
			_baseOffset = offset;
			readEnd = count;
		}
		else
		{
			readEnd = (int)(offset + count - _baseOffset);
			int num = Math.Max(readEnd - _maxSize, 0);
			EnsureBufferSize(readEnd - num, copyContents: true, num);
			readStart = _end;
			readEnd = (int)(offset + count - _baseOffset);
		}
	}

	private void EnsureBufferSize(int reqSize, bool copyContents, int copyOffset)
	{
		byte[] array = _data;
		if (reqSize > _data.Length)
		{
			if (reqSize > _maxSize)
			{
				if (!_wrapper.Source.CanSeek && reqSize - _discardCount > _maxSize)
				{
					throw new InvalidOperationException("Not enough room in the buffer!  Increase the maximum size and try again.");
				}
				int num = reqSize - _maxSize;
				copyOffset += num;
				reqSize = _maxSize;
			}
			else
			{
				int num2;
				for (num2 = _data.Length; num2 < reqSize; num2 *= 2)
				{
				}
				reqSize = num2;
			}
			if (reqSize > _data.Length)
			{
				array = new byte[reqSize];
			}
		}
		if (copyContents)
		{
			if ((copyOffset > 0 && copyOffset < _end) || (copyOffset == 0 && array != _data))
			{
				Buffer.BlockCopy(_data, copyOffset, array, 0, _end - copyOffset);
				if ((_discardCount -= copyOffset) < 0)
				{
					_discardCount = 0;
				}
			}
			else if (copyOffset < 0 && -copyOffset < _end)
			{
				if (array != _data || _end <= -copyOffset)
				{
					Buffer.BlockCopy(_data, 0, array, -copyOffset, Math.Max(_end, Math.Min(_end, _data.Length + copyOffset)));
				}
				else
				{
					_end = copyOffset;
				}
				_discardCount = 0;
			}
			else
			{
				_end = copyOffset;
				_discardCount = 0;
			}
			_baseOffset += copyOffset;
			_end -= copyOffset;
			if (_end > array.Length)
			{
				_end = array.Length;
			}
		}
		else
		{
			_discardCount = 0;
			_end = 0;
		}
		_data = array;
	}

	private int FillBuffer(long offset, int count, int readStart, int readEnd)
	{
		long readOffset = _baseOffset + readStart;
		int readCount = readEnd - readStart;
		lock (_wrapper.LockObject)
		{
			readCount = PrepareStreamForRead(readCount, readOffset);
			ReadStream(readStart, readCount, readOffset);
			if (_end < readStart + readCount)
			{
				count = Math.Max(0, (int)(_baseOffset + _end - offset));
			}
			else if (!_minimalRead && _end < _data.Length)
			{
				readCount = _data.Length - _end;
				readCount = PrepareStreamForRead(readCount, _baseOffset + _end);
				_end += _wrapper.Source.Read(_data, _end, readCount);
			}
		}
		return count;
	}

	private int PrepareStreamForRead(int readCount, long readOffset)
	{
		if (readCount > 0 && _wrapper.Source.Position != readOffset)
		{
			if (readOffset < _wrapper.EofOffset)
			{
				if (_wrapper.Source.CanSeek)
				{
					_wrapper.Source.Position = readOffset;
				}
				else
				{
					long num = readOffset - _wrapper.Source.Position;
					if (num < 0)
					{
						readCount = 0;
					}
					else
					{
						while (--num >= 0)
						{
							if (_wrapper.Source.ReadByte() == -1)
							{
								_wrapper.EofOffset = _wrapper.Source.Position;
								readCount = 0;
								break;
							}
						}
					}
				}
			}
			else
			{
				readCount = 0;
			}
		}
		return readCount;
	}

	private void ReadStream(int readStart, int readCount, long readOffset)
	{
		while (readCount > 0 && readOffset < _wrapper.EofOffset)
		{
			int num = _wrapper.Source.Read(_data, readStart, readCount);
			if (num == 0)
			{
				break;
			}
			readStart += num;
			readOffset += num;
			readCount -= num;
		}
		if (readStart > _end)
		{
			_end = readStart;
		}
	}

	public void DiscardThrough(long offset)
	{
		int val = (int)(offset - _baseOffset);
		_discardCount = Math.Max(val, _discardCount);
		if (_discardCount >= _data.Length)
		{
			CommitDiscard();
		}
	}

	private void CommitDiscard()
	{
		if (_discardCount >= _data.Length || _discardCount >= _end)
		{
			_baseOffset += _discardCount;
			_end = 0;
		}
		else
		{
			Buffer.BlockCopy(_data, _discardCount, _data, 0, _end - _discardCount);
			_baseOffset += _discardCount;
			_end -= _discardCount;
		}
		_discardCount = 0;
	}
}

CustomBoomboxTracks.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Concentus;
using Concentus.Oggfile;
using CustomBoomboxTracks.Configuration;
using CustomBoomboxTracks.Managers;
using CustomBoomboxTracks.Utilities;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomBoomboxTracks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0")]
[assembly: AssemblyProduct("CustomBoomboxTracks")]
[assembly: AssemblyTitle("CustomBoomboxTracks")]
[assembly: AssemblyVersion("1.4.0.0")]
namespace CustomBoomboxTracks
{
	[BepInPlugin("boomboxmusicopus", "Custom Boombox Music Opus", "1.4.0")]
	public class BoomboxPlugin : BaseUnityPlugin
	{
		private const string GUID = "boomboxmusicopus";

		private const string NAME = "Custom Boombox Music Opus";

		private const string VERSION = "1.4.0";

		private static BoomboxPlugin Instance;

		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			LogInfo("Loading...");
			Config.Init();
			AudioManager.GenerateFolders();
			new Harmony("boomboxmusicopus").PatchAll();
			LogInfo("Loading Complete!");
		}

		internal static void LogDebug(string message)
		{
			Instance.Log(message, (LogLevel)32);
		}

		internal static void LogInfo(string message)
		{
			Instance.Log(message, (LogLevel)16);
		}

		internal static void LogWarning(string message)
		{
			Instance.Log(message, (LogLevel)4);
		}

		internal static void LogError(string message)
		{
			Instance.Log(message, (LogLevel)2);
		}

		internal static void LogError(Exception ex)
		{
			Instance.Log(ex.Message + "\n" + ex.StackTrace, (LogLevel)2);
		}

		private void Log(string message, LogLevel logLevel)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.Log(logLevel, (object)message);
		}
	}
}
namespace CustomBoomboxTracks.Utilities
{
	public class SharedCoroutineStarter : MonoBehaviour
	{
		private static SharedCoroutineStarter _instance;

		public static Coroutine StartCoroutine(IEnumerator routine)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = new GameObject("Shared Coroutine Starter").AddComponent<SharedCoroutineStarter>();
				Object.DontDestroyOnLoad((Object)(object)_instance);
			}
			return ((MonoBehaviour)_instance).StartCoroutine(routine);
		}
	}
}
namespace CustomBoomboxTracks.Patches
{
	[HarmonyPatch(typeof(BoomboxItem), "PocketItem")]
	internal class BoomboxItem_PocketItem
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			bool flag = false;
			for (int i = 0; i < list.Count; i++)
			{
				if (!flag)
				{
					if (list[i].opcode == OpCodes.Call)
					{
						flag = true;
					}
					continue;
				}
				if (list[i].opcode == OpCodes.Ret)
				{
					break;
				}
				list[i].opcode = OpCodes.Nop;
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(BoomboxItem), "Start")]
	internal class BoomboxItem_Start
	{
		private static void Postfix(BoomboxItem __instance)
		{
			if (AudioManager.FinishedLoading)
			{
				AudioManager.ApplyClips(__instance);
				return;
			}
			AudioManager.OnAllSongsLoaded += delegate
			{
				AudioManager.ApplyClips(__instance);
			};
		}
	}
	[HarmonyPatch(typeof(BoomboxItem), "StartMusic")]
	internal class BoomboxItem_StartMusic
	{
		private static void Postfix(BoomboxItem __instance, bool startMusic)
		{
			if (startMusic)
			{
				BoomboxPlugin.LogInfo("Playing " + ((Object)__instance.boomboxAudio.clip).name);
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "Awake")]
	internal class StartOfRound_Awake
	{
		private static void Prefix()
		{
			AudioManager.Load();
		}
	}
}
namespace CustomBoomboxTracks.Managers
{
	internal static class AudioManager
	{
		private static string[] allSongPaths;

		private static List<AudioClip> clips = new List<AudioClip>();

		private static bool firstRun = true;

		private static bool finishedLoading = false;

		private static readonly string customSongsFolder = Path.Combine(Paths.BepInExRootPath, "Custom Songs", "Boombox Music");

		private static readonly string configFolder = Path.Combine(Paths.ConfigPath, "Custom Songs");

		public static bool FinishedLoading => finishedLoading;

		public static bool HasNoSongs => allSongPaths.Length == 0;

		public static event Action OnAllSongsLoaded;

		public static void GenerateFolders()
		{
			if (Config.DeleteCustomSongsFolder)
			{
				if (Directory.Exists(customSongsFolder))
				{
					Directory.Delete(customSongsFolder, recursive: true);
					BoomboxPlugin.LogInfo("Option was set to true. Deleted " + customSongsFolder);
				}
			}
			else if (Config.UseCustomSongsFolder)
			{
				Directory.CreateDirectory(customSongsFolder);
				BoomboxPlugin.LogInfo("Created directory at " + customSongsFolder);
			}
			if (Config.UseConfigFolder && !Directory.Exists(configFolder))
			{
				Directory.CreateDirectory(configFolder);
				BoomboxPlugin.LogInfo("Created directory at " + configFolder);
			}
		}

		public static void Load()
		{
			if (!firstRun)
			{
				return;
			}
			firstRun = false;
			allSongPaths = SearchForSongs().ToArray();
			if (allSongPaths.Length == 0)
			{
				BoomboxPlugin.LogWarning("No songs found!");
				return;
			}
			BoomboxPlugin.LogInfo("Preparing to load AudioClips...");
			List<Coroutine> list = new List<Coroutine>();
			string[] array = allSongPaths;
			for (int i = 0; i < array.Length; i++)
			{
				Coroutine item = SharedCoroutineStarter.StartCoroutine(LoadAudioClip(array[i]));
				list.Add(item);
			}
			SharedCoroutineStarter.StartCoroutine(WaitForAllClips(list));
		}

		private static IEnumerable<string> SearchForSongs()
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<string> enumerable = new List<string>();
			if (Config.UseCustomSongsFolder && Directory.Exists(customSongsFolder))
			{
				enumerable = enumerable.Concat(Directory.GetFiles(customSongsFolder));
				BoomboxPlugin.LogInfo("Pulling songs from " + customSongsFolder);
			}
			if (Config.UseConfigFolder && Directory.Exists(configFolder))
			{
				enumerable = enumerable.Concat(Directory.GetFiles(configFolder));
				BoomboxPlugin.LogInfo("Pulling songs from " + configFolder);
			}
			if (Config.SearchForCustomSongs)
			{
				BoomboxPlugin.LogInfo("Searching for custom songs!");
				string[] directories = Directory.GetDirectories(Paths.PluginPath);
				for (int i = 0; i < directories.Length; i++)
				{
					string text = Path.Combine(directories[i], "Custom Songs");
					if (!Directory.Exists(text))
					{
						continue;
					}
					BoomboxPlugin.LogInfo("Found some in " + text);
					string[] files = Directory.GetFiles(text);
					foreach (string text2 in files)
					{
						if ((int)GetAudioType(text2) == 0 && !GetIsOpus(text2))
						{
							BoomboxPlugin.LogWarning("Not a valid song " + text2);
							continue;
						}
						BoomboxPlugin.LogInfo("Song found " + text2);
						enumerable = CollectionExtensions.AddItem<string>(enumerable, text2);
					}
				}
			}
			return enumerable;
		}

		private static IEnumerator LoadAudioClip(string filePath)
		{
			BoomboxPlugin.LogInfo("Loading " + filePath + "!");
			AudioType audioType = GetAudioType(filePath);
			if ((int)audioType == 0)
			{
				if (GetIsOpus(filePath))
				{
					yield return LoadOpus(filePath);
				}
				else
				{
					BoomboxPlugin.LogError("Failed to load AudioClip from " + filePath + "\nUnsupported file extension!");
				}
			}
			else
			{
				yield return LoadNormally(filePath, audioType);
			}
		}

		private static IEnumerator LoadOpus(string filePath)
		{
			BoomboxPlugin.LogInfo("It's an Opus file!");
			List<float> list = new List<float>();
			using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
			{
				IOpusDecoder val = OpusCodecFactory.CreateDecoder(Config.OpusDecodeSampleRate, 1, Console.Out);
				OpusOggReadStream val2 = new OpusOggReadStream(val, (Stream)fileStream);
				while (val2.HasNextPacket)
				{
					short[] array = val2.DecodeNextPacket();
					if (array != null)
					{
						float[] array2 = new float[array.Length];
						for (int i = 0; i < array.Length; i++)
						{
							array2[i] = (float)array[i] / 32768f;
						}
						list.AddRange(array2);
					}
				}
				((IDisposable)val).Dispose();
				fileStream.Dispose();
			}
			AudioClip val3 = AudioClip.Create(Path.GetFileName(filePath), list.Count, 1, Config.OpusDecodeSampleRate, false);
			val3.SetData(list.ToArray(), 0);
			clips.Add(val3);
			list.Clear();
			BoomboxPlugin.LogInfo("Loaded Opus file " + filePath);
			yield break;
		}

		private static IEnumerator LoadNormally(string filePath, AudioType audioType)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			BoomboxPlugin.LogInfo("It's a normal file!");
			UnityWebRequest loader = UnityWebRequestMultimedia.GetAudioClip(filePath, audioType);
			if (Config.StreamFromDisk)
			{
				DownloadHandler downloadHandler = loader.downloadHandler;
				((DownloadHandlerAudioClip)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null)).streamAudio = true;
			}
			loader.SendWebRequest();
			while (!loader.isDone)
			{
				yield return null;
			}
			if (loader.error != null)
			{
				BoomboxPlugin.LogError("Error loading clip from path: " + filePath + "\n" + loader.error);
				BoomboxPlugin.LogError(loader.error);
				yield break;
			}
			AudioClip content = DownloadHandlerAudioClip.GetContent(loader);
			if (Object.op_Implicit((Object)(object)content) && (int)content.loadState == 2)
			{
				BoomboxPlugin.LogInfo("Loaded normal file " + filePath);
				((Object)content).name = Path.GetFileName(filePath);
				clips.Add(content);
			}
			else
			{
				BoomboxPlugin.LogError("Failed to load clip at: " + filePath + "\nThis might be due to an mismatch between the audio codec and the file extension!");
			}
		}

		private static IEnumerator WaitForAllClips(List<Coroutine> coroutines)
		{
			foreach (Coroutine coroutine in coroutines)
			{
				yield return coroutine;
			}
			clips.Sort((AudioClip first, AudioClip second) => ((Object)first).name.CompareTo(((Object)second).name));
			finishedLoading = true;
			AudioManager.OnAllSongsLoaded?.Invoke();
			AudioManager.OnAllSongsLoaded = null;
		}

		public static void ApplyClips(BoomboxItem __instance)
		{
			BoomboxPlugin.LogInfo("Applying clips!");
			if (Config.UseDefaultSongs)
			{
				__instance.musicAudios = __instance.musicAudios.Concat(clips).ToArray();
			}
			else
			{
				__instance.musicAudios = clips.ToArray();
			}
			BoomboxPlugin.LogInfo($"Total Clip Count: {__instance.musicAudios.Length}");
		}

		private static AudioType GetAudioType(string path)
		{
			return (AudioType)(Path.GetExtension(path).ToLower() switch
			{
				".wav" => 20, 
				".ogg" => 14, 
				".mp3" => 13, 
				_ => 0, 
			});
		}

		private static bool GetIsOpus(string path)
		{
			return Path.GetExtension(path).ToLower() == ".opus";
		}
	}
}
namespace CustomBoomboxTracks.Configuration
{
	internal static class Config
	{
		private const string CONFIG_FILE_NAME = "boombox.cfg";

		private static ConfigFile _config;

		private static ConfigEntry<bool> _useDefaultSongs;

		private static ConfigEntry<bool> _streamAudioFromDisk;

		private static ConfigEntry<int> _opusDecodeSampleRate;

		private static ConfigEntry<bool> _useCustomSongsFolder;

		private static ConfigEntry<bool> _useConfigFolder;

		private static ConfigEntry<bool> _searchForCustomSongs;

		private static ConfigEntry<bool> _deleteCustomSongsFolder;

		public static bool UseDefaultSongs
		{
			get
			{
				if (!_useDefaultSongs.Value)
				{
					return AudioManager.HasNoSongs;
				}
				return true;
			}
		}

		public static bool StreamFromDisk => _streamAudioFromDisk.Value;

		public static int OpusDecodeSampleRate => _opusDecodeSampleRate.Value;

		public static bool UseCustomSongsFolder => _useCustomSongsFolder.Value;

		public static bool UseConfigFolder => _useConfigFolder.Value;

		public static bool SearchForCustomSongs => _searchForCustomSongs.Value;

		public static bool DeleteCustomSongsFolder => _deleteCustomSongsFolder.Value;

		public static void Init()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			BoomboxPlugin.LogInfo("Initializing config...");
			_config = new ConfigFile(Path.Combine(Paths.ConfigPath, "boombox.cfg"), true);
			_useDefaultSongs = _config.Bind<bool>("Config", "Use Default Songs", false, "Include the default songs in the rotation.");
			_streamAudioFromDisk = _config.Bind<bool>("Config", "Stream Audio From Disk", false, "(Not possible for Opus) Requires less memory and takes less time to load, but prevents playing the same song twice at once.");
			_opusDecodeSampleRate = _config.Bind<int>("Config", "Opus Decoding Sample Rate", 16000, "Higher values provide better quality, but use more memory. I think the supported values are 8000, 16000, 32000, and 48000 (not 41800). I've set the default to 16000 because slightly lower quality is funny.");
			_useCustomSongsFolder = _config.Bind<bool>("Config", "Use Custom Songs Folder", true, "Pull songs from the `Custom Songs/Boombox Music` folder. I don't think anyone ever pulls songs from here.");
			_useConfigFolder = _config.Bind<bool>("Config", "Use Config Folder", false, "Pull songs from the `Config/Custom Songs` folder. In case you share your songs via Thunderstore codes.");
			_searchForCustomSongs = _config.Bind<bool>("Config", "Search For Custom Songs", true, "Searches and pulls for songs from any downloaded Plugins or other Mods (in their Custom Songs folders). So you don't need any \"Fix\" mods.");
			_deleteCustomSongsFolder = _config.Bind<bool>("Config", "Delete Custom Songs Folder", false, "A lot of \"Fix\" mods just copy songs to the right spot, doubling the amount of space used. This option will clean that up for you. False by default to prevent accidental unwanted behaviour.");
			BoomboxPlugin.LogInfo("Config initialized!");
		}

		private static void PrintConfig()
		{
			BoomboxPlugin.LogInfo($"Use Default Songs: {_useDefaultSongs.Value}");
			BoomboxPlugin.LogInfo($"Stream From Disk: {_streamAudioFromDisk}");
			BoomboxPlugin.LogInfo($"Opus Decoding Sample Rate: {_opusDecodeSampleRate}");
			BoomboxPlugin.LogInfo($"Use Custom Songs Folder: {_useCustomSongsFolder}");
			BoomboxPlugin.LogInfo($"Use Config Folder: {_useConfigFolder}");
			BoomboxPlugin.LogInfo($"Search For Custom Songs: {_searchForCustomSongs}");
			BoomboxPlugin.LogInfo($"Delete Custom Songs Folder: {_deleteCustomSongsFolder}");
		}
	}
}

System.Buffers.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using FxResources.System.Buffers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyTitle("System.Buffers")]
[assembly: AssemblyDescription("System.Buffers")]
[assembly: AssemblyDefaultAlias("System.Buffers")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyFileVersion("4.6.28619.01")]
[assembly: AssemblyInformationalVersion("4.6.28619.01 @BuiltBy: dlab14-DDVSOWINAGE069 @Branch: release/2.1 @SrcCode: https://github.com/dotnet/corefx/tree/7601f4f6225089ffb291dc7d58293c7bbf5c5d4f")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.0.3.0")]
[module: UnverifiableCode]
namespace FxResources.System.Buffers
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static ResourceManager s_resourceManager;

		private static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(ResourceType));

		internal static Type ResourceType { get; } = typeof(SR);


		internal static string ArgumentException_BufferNotFromPool => GetResourceString("ArgumentException_BufferNotFromPool", null);

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool UsingResourceKeys()
		{
			return false;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string text = null;
			try
			{
				text = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			if (defaultString != null && resourceKey.Equals(text, StringComparison.Ordinal))
			{
				return defaultString;
			}
			return text;
		}

		internal static string Format(string resourceFormat, params object[] args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object p1, object p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object p1, object p2, object p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.All)]
	internal class __BlockReflectionAttribute : Attribute
	{
	}
}
namespace System.Buffers
{
	public abstract class ArrayPool<T>
	{
		private static ArrayPool<T> s_sharedInstance;

		public static ArrayPool<T> Shared
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static ArrayPool<T> EnsureSharedCreated()
		{
			Interlocked.CompareExchange(ref s_sharedInstance, Create(), null);
			return s_sharedInstance;
		}

		public static ArrayPool<T> Create()
		{
			return new DefaultArrayPool<T>();
		}

		public static ArrayPool<T> Create(int maxArrayLength, int maxArraysPerBucket)
		{
			return new DefaultArrayPool<T>(maxArrayLength, maxArraysPerBucket);
		}

		public abstract T[] Rent(int minimumLength);

		public abstract void Return(T[] array, bool clearArray = false);
	}
	[EventSource(Name = "System.Buffers.ArrayPoolEventSource")]
	internal sealed class ArrayPoolEventSource : EventSource
	{
		internal enum BufferAllocatedReason
		{
			Pooled,
			OverMaximumSize,
			PoolExhausted
		}

		internal static readonly System.Buffers.ArrayPoolEventSource Log = new System.Buffers.ArrayPoolEventSource();

		[Event(1, Level = EventLevel.Verbose)]
		internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId)
		{
			EventData* ptr = stackalloc EventData[4];
			*ptr = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&bufferId)
			};
			ptr[1] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&bufferSize)
			};
			ptr[2] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&poolId)
			};
			ptr[3] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&bucketId)
			};
			WriteEventCore(1, 4, ptr);
		}

		[Event(2, Level = EventLevel.Informational)]
		internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason)
		{
			EventData* ptr = stackalloc EventData[5];
			*ptr = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&bufferId)
			};
			ptr[1] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&bufferSize)
			};
			ptr[2] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&poolId)
			};
			ptr[3] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&bucketId)
			};
			ptr[4] = new EventData
			{
				Size = 4,
				DataPointer = (IntPtr)(&reason)
			};
			WriteEventCore(2, 5, ptr);
		}

		[Event(3, Level = EventLevel.Verbose)]
		internal void BufferReturned(int bufferId, int bufferSize, int poolId)
		{
			WriteEvent(3, bufferId, bufferSize, poolId);
		}
	}
	internal sealed class DefaultArrayPool<T> : ArrayPool<T>
	{
		private sealed class Bucket
		{
			internal readonly int _bufferLength;

			private readonly T[][] _buffers;

			private readonly int _poolId;

			private SpinLock _lock;

			private int _index;

			internal int Id => GetHashCode();

			internal Bucket(int bufferLength, int numberOfBuffers, int poolId)
			{
				_lock = new SpinLock(Debugger.IsAttached);
				_buffers = new T[numberOfBuffers][];
				_bufferLength = bufferLength;
				_poolId = poolId;
			}

			internal T[] Rent()
			{
				T[][] buffers = _buffers;
				T[] array = null;
				bool lockTaken = false;
				bool flag = false;
				try
				{
					_lock.Enter(ref lockTaken);
					if (_index < buffers.Length)
					{
						array = buffers[_index];
						buffers[_index++] = null;
						flag = array == null;
					}
				}
				finally
				{
					if (lockTaken)
					{
						_lock.Exit(useMemoryBarrier: false);
					}
				}
				if (flag)
				{
					array = new T[_bufferLength];
					System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log;
					if (log.IsEnabled())
					{
						log.BufferAllocated(array.GetHashCode(), _bufferLength, _poolId, Id, System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.Pooled);
					}
				}
				return array;
			}

			internal void Return(T[] array)
			{
				if (array.Length != _bufferLength)
				{
					throw new ArgumentException(System.SR.ArgumentException_BufferNotFromPool, "array");
				}
				bool lockTaken = false;
				try
				{
					_lock.Enter(ref lockTaken);
					if (_index != 0)
					{
						_buffers[--_index] = array;
					}
				}
				finally
				{
					if (lockTaken)
					{
						_lock.Exit(useMemoryBarrier: false);
					}
				}
			}
		}

		private const int DefaultMaxArrayLength = 1048576;

		private const int DefaultMaxNumberOfArraysPerBucket = 50;

		private static T[] s_emptyArray;

		private readonly Bucket[] _buckets;

		private int Id => GetHashCode();

		internal DefaultArrayPool()
			: this(1048576, 50)
		{
		}

		internal DefaultArrayPool(int maxArrayLength, int maxArraysPerBucket)
		{
			if (maxArrayLength <= 0)
			{
				throw new ArgumentOutOfRangeException("maxArrayLength");
			}
			if (maxArraysPerBucket <= 0)
			{
				throw new ArgumentOutOfRangeException("maxArraysPerBucket");
			}
			if (maxArrayLength > 1073741824)
			{
				maxArrayLength = 1073741824;
			}
			else if (maxArrayLength < 16)
			{
				maxArrayLength = 16;
			}
			int id = Id;
			int num = System.Buffers.Utilities.SelectBucketIndex(maxArrayLength);
			Bucket[] array = new Bucket[num + 1];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Bucket(System.Buffers.Utilities.GetMaxSizeForBucket(i), maxArraysPerBucket, id);
			}
			_buckets = array;
		}

		public override T[] Rent(int minimumLength)
		{
			if (minimumLength < 0)
			{
				throw new ArgumentOutOfRangeException("minimumLength");
			}
			if (minimumLength == 0)
			{
				return s_emptyArray ?? (s_emptyArray = new T[0]);
			}
			System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log;
			T[] array = null;
			int num = System.Buffers.Utilities.SelectBucketIndex(minimumLength);
			if (num < _buckets.Length)
			{
				int num2 = num;
				do
				{
					array = _buckets[num2].Rent();
					if (array != null)
					{
						if (log.IsEnabled())
						{
							log.BufferRented(array.GetHashCode(), array.Length, Id, _buckets[num2].Id);
						}
						return array;
					}
				}
				while (++num2 < _buckets.Length && num2 != num + 2);
				array = new T[_buckets[num]._bufferLength];
			}
			else
			{
				array = new T[minimumLength];
			}
			if (log.IsEnabled())
			{
				int hashCode = array.GetHashCode();
				int bucketId = -1;
				log.BufferRented(hashCode, array.Length, Id, bucketId);
				log.BufferAllocated(hashCode, array.Length, Id, bucketId, (num >= _buckets.Length) ? System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.OverMaximumSize : System.Buffers.ArrayPoolEventSource.BufferAllocatedReason.PoolExhausted);
			}
			return array;
		}

		public override void Return(T[] array, bool clearArray = false)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (array.Length == 0)
			{
				return;
			}
			int num = System.Buffers.Utilities.SelectBucketIndex(array.Length);
			if (num < _buckets.Length)
			{
				if (clearArray)
				{
					Array.Clear(array, 0, array.Length);
				}
				_buckets[num].Return(array);
			}
			System.Buffers.ArrayPoolEventSource log = System.Buffers.ArrayPoolEventSource.Log;
			if (log.IsEnabled())
			{
				log.BufferReturned(array.GetHashCode(), array.Length, Id);
			}
		}
	}
	internal static class Utilities
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static int SelectBucketIndex(int bufferSize)
		{
			uint num = (uint)(bufferSize - 1) >> 4;
			int num2 = 0;
			if (num > 65535)
			{
				num >>= 16;
				num2 = 16;
			}
			if (num > 255)
			{
				num >>= 8;
				num2 += 8;
			}
			if (num > 15)
			{
				num >>= 4;
				num2 += 4;
			}
			if (num > 3)
			{
				num >>= 2;
				num2 += 2;
			}
			if (num > 1)
			{
				num >>= 1;
				num2++;
			}
			return num2 + (int)num;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static int GetMaxSizeForBucket(int binIndex)
		{
			return 16 << binIndex;
		}
	}
}

System.Memory.dll

Decompiled 2 months ago
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Buffers.Text;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using System.Numerics.Hashing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using FxResources.System.Memory;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyTitle("System.Memory")]
[assembly: AssemblyDescription("System.Memory")]
[assembly: AssemblyDefaultAlias("System.Memory")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyFileVersion("4.6.31308.01")]
[assembly: AssemblyInformationalVersion("4.6.31308.01 @BuiltBy: cloudtest-841353dfc000000 @Branch: release/2.1-MSRC @SrcCode: https://github.com/dotnet/corefx/tree/32b491939fbd125f304031c35038b1e14b4e3958")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.0.1.2")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsByRefLikeAttribute : Attribute
	{
	}
}
namespace FxResources.System.Memory
{
	internal static class SR
	{
	}
}
namespace System
{
	public readonly struct SequencePosition : IEquatable<SequencePosition>
	{
		private readonly object _object;

		private readonly int _integer;

		public SequencePosition(object @object, int integer)
		{
			_object = @object;
			_integer = integer;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public object GetObject()
		{
			return _object;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public int GetInteger()
		{
			return _integer;
		}

		public bool Equals(SequencePosition other)
		{
			if (_integer == other._integer)
			{
				return object.Equals(_object, other._object);
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public override bool Equals(object obj)
		{
			if (obj is SequencePosition other)
			{
				return Equals(other);
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public override int GetHashCode()
		{
			return HashHelpers.Combine(_object?.GetHashCode() ?? 0, _integer);
		}
	}
	internal static class ThrowHelper
	{
		internal static void ThrowArgumentNullException(System.ExceptionArgument argument)
		{
			throw CreateArgumentNullException(argument);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentNullException(System.ExceptionArgument argument)
		{
			return new ArgumentNullException(argument.ToString());
		}

		internal static void ThrowArrayTypeMismatchException()
		{
			throw CreateArrayTypeMismatchException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArrayTypeMismatchException()
		{
			return new ArrayTypeMismatchException();
		}

		internal static void ThrowArgumentException_InvalidTypeWithPointersNotSupported(Type type)
		{
			throw CreateArgumentException_InvalidTypeWithPointersNotSupported(type);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException_InvalidTypeWithPointersNotSupported(Type type)
		{
			return new ArgumentException(System.SR.Format(System.SR.Argument_InvalidTypeWithPointersNotSupported, type));
		}

		internal static void ThrowArgumentException_DestinationTooShort()
		{
			throw CreateArgumentException_DestinationTooShort();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException_DestinationTooShort()
		{
			return new ArgumentException(System.SR.Argument_DestinationTooShort);
		}

		internal static void ThrowIndexOutOfRangeException()
		{
			throw CreateIndexOutOfRangeException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateIndexOutOfRangeException()
		{
			return new IndexOutOfRangeException();
		}

		internal static void ThrowArgumentOutOfRangeException()
		{
			throw CreateArgumentOutOfRangeException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException()
		{
			return new ArgumentOutOfRangeException();
		}

		internal static void ThrowArgumentOutOfRangeException(System.ExceptionArgument argument)
		{
			throw CreateArgumentOutOfRangeException(argument);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException(System.ExceptionArgument argument)
		{
			return new ArgumentOutOfRangeException(argument.ToString());
		}

		internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
		{
			throw CreateArgumentOutOfRangeException_PrecisionTooLarge();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_PrecisionTooLarge()
		{
			return new ArgumentOutOfRangeException("precision", System.SR.Format(System.SR.Argument_PrecisionTooLarge, (byte)99));
		}

		internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit()
		{
			throw CreateArgumentOutOfRangeException_SymbolDoesNotFit();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_SymbolDoesNotFit()
		{
			return new ArgumentOutOfRangeException("symbol", System.SR.Argument_BadFormatSpecifier);
		}

		internal static void ThrowInvalidOperationException()
		{
			throw CreateInvalidOperationException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException()
		{
			return new InvalidOperationException();
		}

		internal static void ThrowInvalidOperationException_OutstandingReferences()
		{
			throw CreateInvalidOperationException_OutstandingReferences();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException_OutstandingReferences()
		{
			return new InvalidOperationException(System.SR.OutstandingReferences);
		}

		internal static void ThrowInvalidOperationException_UnexpectedSegmentType()
		{
			throw CreateInvalidOperationException_UnexpectedSegmentType();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException_UnexpectedSegmentType()
		{
			return new InvalidOperationException(System.SR.UnexpectedSegmentType);
		}

		internal static void ThrowInvalidOperationException_EndPositionNotReached()
		{
			throw CreateInvalidOperationException_EndPositionNotReached();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateInvalidOperationException_EndPositionNotReached()
		{
			return new InvalidOperationException(System.SR.EndPositionNotReached);
		}

		internal static void ThrowArgumentOutOfRangeException_PositionOutOfRange()
		{
			throw CreateArgumentOutOfRangeException_PositionOutOfRange();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_PositionOutOfRange()
		{
			return new ArgumentOutOfRangeException("position");
		}

		internal static void ThrowArgumentOutOfRangeException_OffsetOutOfRange()
		{
			throw CreateArgumentOutOfRangeException_OffsetOutOfRange();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentOutOfRangeException_OffsetOutOfRange()
		{
			return new ArgumentOutOfRangeException("offset");
		}

		internal static void ThrowObjectDisposedException_ArrayMemoryPoolBuffer()
		{
			throw CreateObjectDisposedException_ArrayMemoryPoolBuffer();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateObjectDisposedException_ArrayMemoryPoolBuffer()
		{
			return new ObjectDisposedException("ArrayMemoryPoolBuffer");
		}

		internal static void ThrowFormatException_BadFormatSpecifier()
		{
			throw CreateFormatException_BadFormatSpecifier();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateFormatException_BadFormatSpecifier()
		{
			return new FormatException(System.SR.Argument_BadFormatSpecifier);
		}

		internal static void ThrowArgumentException_OverlapAlignmentMismatch()
		{
			throw CreateArgumentException_OverlapAlignmentMismatch();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateArgumentException_OverlapAlignmentMismatch()
		{
			return new ArgumentException(System.SR.Argument_OverlapAlignmentMismatch);
		}

		internal static void ThrowNotSupportedException()
		{
			throw CreateThrowNotSupportedException();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static Exception CreateThrowNotSupportedException()
		{
			return new NotSupportedException();
		}

		public static bool TryFormatThrowFormatException(out int bytesWritten)
		{
			bytesWritten = 0;
			ThrowFormatException_BadFormatSpecifier();
			return false;
		}

		public static bool TryParseThrowFormatException<T>(out T value, out int bytesConsumed)
		{
			value = default(T);
			bytesConsumed = 0;
			ThrowFormatException_BadFormatSpecifier();
			return false;
		}

		public static void ThrowArgumentValidationException<T>(ReadOnlySequenceSegment<T> startSegment, int startIndex, ReadOnlySequenceSegment<T> endSegment)
		{
			throw CreateArgumentValidationException(startSegment, startIndex, endSegment);
		}

		private static Exception CreateArgumentValidationException<T>(ReadOnlySequenceSegment<T> startSegment, int startIndex, ReadOnlySequenceSegment<T> endSegment)
		{
			if (startSegment == null)
			{
				return CreateArgumentNullException(System.ExceptionArgument.startSegment);
			}
			if (endSegment == null)
			{
				return CreateArgumentNullException(System.ExceptionArgument.endSegment);
			}
			if (startSegment != endSegment && startSegment.RunningIndex > endSegment.RunningIndex)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.endSegment);
			}
			if ((uint)startSegment.Memory.Length < (uint)startIndex)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.startIndex);
			}
			return CreateArgumentOutOfRangeException(System.ExceptionArgument.endIndex);
		}

		public static void ThrowArgumentValidationException(Array array, int start)
		{
			throw CreateArgumentValidationException(array, start);
		}

		private static Exception CreateArgumentValidationException(Array array, int start)
		{
			if (array == null)
			{
				return CreateArgumentNullException(System.ExceptionArgument.array);
			}
			if ((uint)start > (uint)array.Length)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return CreateArgumentOutOfRangeException(System.ExceptionArgument.length);
		}

		public static void ThrowStartOrEndArgumentValidationException(long start)
		{
			throw CreateStartOrEndArgumentValidationException(start);
		}

		private static Exception CreateStartOrEndArgumentValidationException(long start)
		{
			if (start < 0)
			{
				return CreateArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return CreateArgumentOutOfRangeException(System.ExceptionArgument.length);
		}
	}
	internal enum ExceptionArgument
	{
		length,
		start,
		minimumBufferSize,
		elementIndex,
		comparable,
		comparer,
		destination,
		offset,
		startSegment,
		endSegment,
		startIndex,
		endIndex,
		array,
		culture,
		manager
	}
	internal static class DecimalDecCalc
	{
		private static uint D32DivMod1E9(uint hi32, ref uint lo32)
		{
			ulong num = ((ulong)hi32 << 32) | lo32;
			lo32 = (uint)(num / 1000000000);
			return (uint)(num % 1000000000);
		}

		internal static uint DecDivMod1E9(ref MutableDecimal value)
		{
			return D32DivMod1E9(D32DivMod1E9(D32DivMod1E9(0u, ref value.High), ref value.Mid), ref value.Low);
		}

		internal static void DecAddInt32(ref MutableDecimal value, uint i)
		{
			if (D32AddCarry(ref value.Low, i) && D32AddCarry(ref value.Mid, 1u))
			{
				D32AddCarry(ref value.High, 1u);
			}
		}

		private static bool D32AddCarry(ref uint value, uint i)
		{
			uint num = value;
			uint num2 = (value = num + i);
			if (num2 >= num)
			{
				return num2 < i;
			}
			return true;
		}

		internal static void DecMul10(ref MutableDecimal value)
		{
			MutableDecimal d = value;
			DecShiftLeft(ref value);
			DecShiftLeft(ref value);
			DecAdd(ref value, d);
			DecShiftLeft(ref value);
		}

		private static void DecShiftLeft(ref MutableDecimal value)
		{
			uint num = (((value.Low & 0x80000000u) != 0) ? 1u : 0u);
			uint num2 = (((value.Mid & 0x80000000u) != 0) ? 1u : 0u);
			value.Low <<= 1;
			value.Mid = (value.Mid << 1) | num;
			value.High = (value.High << 1) | num2;
		}

		private static void DecAdd(ref MutableDecimal value, MutableDecimal d)
		{
			if (D32AddCarry(ref value.Low, d.Low) && D32AddCarry(ref value.Mid, 1u))
			{
				D32AddCarry(ref value.High, 1u);
			}
			if (D32AddCarry(ref value.Mid, d.Mid))
			{
				D32AddCarry(ref value.High, 1u);
			}
			D32AddCarry(ref value.High, d.High);
		}
	}
	internal static class Number
	{
		private static class DoubleHelper
		{
			public unsafe static uint Exponent(double d)
			{
				return (*(uint*)((byte*)(&d) + 4) >> 20) & 0x7FFu;
			}

			public unsafe static ulong Mantissa(double d)
			{
				return *(uint*)(&d) | ((ulong)(uint)(*(int*)((byte*)(&d) + 4) & 0xFFFFF) << 32);
			}

			public unsafe static bool Sign(double d)
			{
				return *(uint*)((byte*)(&d) + 4) >> 31 != 0;
			}
		}

		internal const int DECIMAL_PRECISION = 29;

		private static readonly ulong[] s_rgval64Power10 = new ulong[30]
		{
			11529215046068469760uL, 14411518807585587200uL, 18014398509481984000uL, 11258999068426240000uL, 14073748835532800000uL, 17592186044416000000uL, 10995116277760000000uL, 13743895347200000000uL, 17179869184000000000uL, 10737418240000000000uL,
			13421772800000000000uL, 16777216000000000000uL, 10485760000000000000uL, 13107200000000000000uL, 16384000000000000000uL, 14757395258967641293uL, 11805916207174113035uL, 9444732965739290428uL, 15111572745182864686uL, 12089258196146291749uL,
			9671406556917033399uL, 15474250491067253438uL, 12379400392853802751uL, 9903520314283042201uL, 15845632502852867522uL, 12676506002282294018uL, 10141204801825835215uL, 16225927682921336344uL, 12980742146337069075uL, 10384593717069655260uL
		};

		private static readonly sbyte[] s_rgexp64Power10 = new sbyte[15]
		{
			4, 7, 10, 14, 17, 20, 24, 27, 30, 34,
			37, 40, 44, 47, 50
		};

		private static readonly ulong[] s_rgval64Power10By16 = new ulong[42]
		{
			10240000000000000000uL, 11368683772161602974uL, 12621774483536188886uL, 14012984643248170708uL, 15557538194652854266uL, 17272337110188889248uL, 9588073174409622172uL, 10644899600020376798uL, 11818212630765741798uL, 13120851772591970216uL,
			14567071740625403792uL, 16172698447808779622uL, 17955302187076837696uL, 9967194951097567532uL, 11065809325636130658uL, 12285516299433008778uL, 13639663065038175358uL, 15143067982934716296uL, 16812182738118149112uL, 9332636185032188787uL,
			10361307573072618722uL, 16615349947311448416uL, 14965776766268445891uL, 13479973333575319909uL, 12141680576410806707uL, 10936253623915059637uL, 9850501549098619819uL, 17745086042373215136uL, 15983352577617880260uL, 14396524142538228461uL,
			12967236152753103031uL, 11679847981112819795uL, 10520271803096747049uL, 9475818434452569218uL, 17070116948172427008uL, 15375394465392026135uL, 13848924157002783096uL, 12474001934591998882uL, 11235582092889474480uL, 10120112665365530972uL,
			18230774251475056952uL, 16420821625123739930uL
		};

		private static readonly short[] s_rgexp64Power10By16 = new short[21]
		{
			54, 107, 160, 213, 266, 319, 373, 426, 479, 532,
			585, 638, 691, 745, 798, 851, 904, 957, 1010, 1064,
			1117
		};

		public static void RoundNumber(ref NumberBuffer number, int pos)
		{
			Span<byte> digits = number.Digits;
			int i;
			for (i = 0; i < pos && digits[i] != 0; i++)
			{
			}
			if (i == pos && digits[i] >= 53)
			{
				while (i > 0 && digits[i - 1] == 57)
				{
					i--;
				}
				if (i > 0)
				{
					digits[i - 1]++;
				}
				else
				{
					number.Scale++;
					digits[0] = 49;
					i = 1;
				}
			}
			else
			{
				while (i > 0 && digits[i - 1] == 48)
				{
					i--;
				}
			}
			if (i == 0)
			{
				number.Scale = 0;
				number.IsNegative = false;
			}
			digits[i] = 0;
		}

		internal static bool NumberBufferToDouble(ref NumberBuffer number, out double value)
		{
			double num = NumberToDouble(ref number);
			uint num2 = DoubleHelper.Exponent(num);
			ulong num3 = DoubleHelper.Mantissa(num);
			switch (num2)
			{
			case 2047u:
				value = 0.0;
				return false;
			case 0u:
				if (num3 == 0L)
				{
					num = 0.0;
				}
				break;
			}
			value = num;
			return true;
		}

		public unsafe static bool NumberBufferToDecimal(ref NumberBuffer number, ref decimal value)
		{
			MutableDecimal source = default(MutableDecimal);
			byte* ptr = number.UnsafeDigits;
			int num = number.Scale;
			if (*ptr == 0)
			{
				if (num > 0)
				{
					num = 0;
				}
			}
			else
			{
				if (num > 29)
				{
					return false;
				}
				while ((num > 0 || (*ptr != 0 && num > -28)) && (source.High < 429496729 || (source.High == 429496729 && (source.Mid < 2576980377u || (source.Mid == 2576980377u && (source.Low < 2576980377u || (source.Low == 2576980377u && *ptr <= 53)))))))
				{
					DecimalDecCalc.DecMul10(ref source);
					if (*ptr != 0)
					{
						DecimalDecCalc.DecAddInt32(ref source, (uint)(*(ptr++) - 48));
					}
					num--;
				}
				if (*(ptr++) >= 53)
				{
					bool flag = true;
					if (*(ptr - 1) == 53 && *(ptr - 2) % 2 == 0)
					{
						int num2 = 20;
						while (*ptr == 48 && num2 != 0)
						{
							ptr++;
							num2--;
						}
						if (*ptr == 0 || num2 == 0)
						{
							flag = false;
						}
					}
					if (flag)
					{
						DecimalDecCalc.DecAddInt32(ref source, 1u);
						if ((source.High | source.Mid | source.Low) == 0)
						{
							source.High = 429496729u;
							source.Mid = 2576980377u;
							source.Low = 2576980378u;
							num++;
						}
					}
				}
			}
			if (num > 0)
			{
				return false;
			}
			if (num <= -29)
			{
				source.High = 0u;
				source.Low = 0u;
				source.Mid = 0u;
				source.Scale = 28;
			}
			else
			{
				source.Scale = -num;
			}
			source.IsNegative = number.IsNegative;
			value = Unsafe.As<MutableDecimal, decimal>(ref source);
			return true;
		}

		public static void DecimalToNumber(decimal value, ref NumberBuffer number)
		{
			ref MutableDecimal reference = ref Unsafe.As<decimal, MutableDecimal>(ref value);
			Span<byte> digits = number.Digits;
			number.IsNegative = reference.IsNegative;
			int num = 29;
			while ((reference.Mid != 0) | (reference.High != 0))
			{
				uint num2 = DecimalDecCalc.DecDivMod1E9(ref reference);
				for (int i = 0; i < 9; i++)
				{
					digits[--num] = (byte)(num2 % 10 + 48);
					num2 /= 10;
				}
			}
			for (uint num3 = reference.Low; num3 != 0; num3 /= 10)
			{
				digits[--num] = (byte)(num3 % 10 + 48);
			}
			int num4 = 29 - num;
			number.Scale = num4 - reference.Scale;
			Span<byte> digits2 = number.Digits;
			int index = 0;
			while (--num4 >= 0)
			{
				digits2[index++] = digits[num++];
			}
			digits2[index] = 0;
		}

		private static uint DigitsToInt(ReadOnlySpan<byte> digits, int count)
		{
			uint value;
			int bytesConsumed;
			bool flag = Utf8Parser.TryParse(digits.Slice(0, count), out value, out bytesConsumed, 'D');
			return value;
		}

		private static ulong Mul32x32To64(uint a, uint b)
		{
			return (ulong)a * (ulong)b;
		}

		private static ulong Mul64Lossy(ulong a, ulong b, ref int pexp)
		{
			ulong num = Mul32x32To64((uint)(a >> 32), (uint)(b >> 32)) + (Mul32x32To64((uint)(a >> 32), (uint)b) >> 32) + (Mul32x32To64((uint)a, (uint)(b >> 32)) >> 32);
			if ((num & 0x8000000000000000uL) == 0L)
			{
				num <<= 1;
				pexp--;
			}
			return num;
		}

		private static int abs(int value)
		{
			if (value < 0)
			{
				return -value;
			}
			return value;
		}

		private unsafe static double NumberToDouble(ref NumberBuffer number)
		{
			ReadOnlySpan<byte> digits = number.Digits;
			int i = 0;
			int numDigits = number.NumDigits;
			int num = numDigits;
			for (; digits[i] == 48; i++)
			{
				num--;
			}
			if (num == 0)
			{
				return 0.0;
			}
			int num2 = Math.Min(num, 9);
			num -= num2;
			ulong num3 = DigitsToInt(digits, num2);
			if (num > 0)
			{
				num2 = Math.Min(num, 9);
				num -= num2;
				uint b = (uint)(s_rgval64Power10[num2 - 1] >> 64 - s_rgexp64Power10[num2 - 1]);
				num3 = Mul32x32To64((uint)num3, b) + DigitsToInt(digits.Slice(9), num2);
			}
			int num4 = number.Scale - (numDigits - num);
			int num5 = abs(num4);
			if (num5 >= 352)
			{
				ulong num6 = ((num4 > 0) ? 9218868437227405312uL : 0);
				if (number.IsNegative)
				{
					num6 |= 0x8000000000000000uL;
				}
				return *(double*)(&num6);
			}
			int pexp = 64;
			if ((num3 & 0xFFFFFFFF00000000uL) == 0L)
			{
				num3 <<= 32;
				pexp -= 32;
			}
			if ((num3 & 0xFFFF000000000000uL) == 0L)
			{
				num3 <<= 16;
				pexp -= 16;
			}
			if ((num3 & 0xFF00000000000000uL) == 0L)
			{
				num3 <<= 8;
				pexp -= 8;
			}
			if ((num3 & 0xF000000000000000uL) == 0L)
			{
				num3 <<= 4;
				pexp -= 4;
			}
			if ((num3 & 0xC000000000000000uL) == 0L)
			{
				num3 <<= 2;
				pexp -= 2;
			}
			if ((num3 & 0x8000000000000000uL) == 0L)
			{
				num3 <<= 1;
				pexp--;
			}
			int num7 = num5 & 0xF;
			if (num7 != 0)
			{
				int num8 = s_rgexp64Power10[num7 - 1];
				pexp += ((num4 < 0) ? (-num8 + 1) : num8);
				ulong b2 = s_rgval64Power10[num7 + ((num4 < 0) ? 15 : 0) - 1];
				num3 = Mul64Lossy(num3, b2, ref pexp);
			}
			num7 = num5 >> 4;
			if (num7 != 0)
			{
				int num9 = s_rgexp64Power10By16[num7 - 1];
				pexp += ((num4 < 0) ? (-num9 + 1) : num9);
				ulong b3 = s_rgval64Power10By16[num7 + ((num4 < 0) ? 21 : 0) - 1];
				num3 = Mul64Lossy(num3, b3, ref pexp);
			}
			if (((uint)(int)num3 & 0x400u) != 0)
			{
				ulong num10 = num3 + 1023 + (ulong)(((int)num3 >> 11) & 1);
				if (num10 < num3)
				{
					num10 = (num10 >> 1) | 0x8000000000000000uL;
					pexp++;
				}
				num3 = num10;
			}
			pexp += 1022;
			num3 = ((pexp <= 0) ? ((pexp == -52 && num3 >= 9223372036854775896uL) ? 1 : ((pexp > -52) ? (num3 >> -pexp + 11 + 1) : 0)) : ((pexp < 2047) ? ((ulong)((long)pexp << 52) + ((num3 >> 11) & 0xFFFFFFFFFFFFFL)) : 9218868437227405312uL));
			if (number.IsNegative)
			{
				num3 |= 0x8000000000000000uL;
			}
			return *(double*)(&num3);
		}
	}
	internal ref struct NumberBuffer
	{
		public int Scale;

		public bool IsNegative;

		public const int BufferSize = 51;

		private byte _b0;

		private byte _b1;

		private byte _b2;

		private byte _b3;

		private byte _b4;

		private byte _b5;

		private byte _b6;

		private byte _b7;

		private byte _b8;

		private byte _b9;

		private byte _b10;

		private byte _b11;

		private byte _b12;

		private byte _b13;

		private byte _b14;

		private byte _b15;

		private byte _b16;

		private byte _b17;

		private byte _b18;

		private byte _b19;

		private byte _b20;

		private byte _b21;

		private byte _b22;

		private byte _b23;

		private byte _b24;

		private byte _b25;

		private byte _b26;

		private byte _b27;

		private byte _b28;

		private byte _b29;

		private byte _b30;

		private byte _b31;

		private byte _b32;

		private byte _b33;

		private byte _b34;

		private byte _b35;

		private byte _b36;

		private byte _b37;

		private byte _b38;

		private byte _b39;

		private byte _b40;

		private byte _b41;

		private byte _b42;

		private byte _b43;

		private byte _b44;

		private byte _b45;

		private byte _b46;

		private byte _b47;

		private byte _b48;

		private byte _b49;

		private byte _b50;

		public unsafe Span<byte> Digits => new Span<byte>(Unsafe.AsPointer(ref _b0), 51);

		public unsafe byte* UnsafeDigits => (byte*)Unsafe.AsPointer(ref _b0);

		public int NumDigits => Digits.IndexOf<byte>(0);

		[Conditional("DEBUG")]
		public void CheckConsistency()
		{
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('[');
			stringBuilder.Append('"');
			Span<byte> digits = Digits;
			for (int i = 0; i < 51; i++)
			{
				byte b = digits[i];
				if (b == 0)
				{
					break;
				}
				stringBuilder.Append((char)b);
			}
			stringBuilder.Append('"');
			stringBuilder.Append(", Scale = " + Scale);
			stringBuilder.Append(", IsNegative   = " + IsNegative);
			stringBuilder.Append(']');
			return stringBuilder.ToString();
		}
	}
	[DebuggerTypeProxy(typeof(System.MemoryDebugView<>))]
	[DebuggerDisplay("{ToString(),raw}")]
	public readonly struct Memory<T>
	{
		private readonly object _object;

		private readonly int _index;

		private readonly int _length;

		private const int RemoveFlagsBitMask = int.MaxValue;

		public static Memory<T> Empty => default(Memory<T>);

		public int Length => _length & 0x7FFFFFFF;

		public bool IsEmpty => (_length & 0x7FFFFFFF) == 0;

		public Span<T> Span
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				Span<T> result;
				if (_index < 0)
				{
					result = ((MemoryManager<T>)_object).GetSpan();
					return result.Slice(_index & 0x7FFFFFFF, _length);
				}
				if (typeof(T) == typeof(char) && _object is string text)
				{
					result = new Span<T>(Unsafe.As<Pinnable<T>>(text), MemoryExtensions.StringAdjustment, text.Length);
					return result.Slice(_index, _length);
				}
				if (_object != null)
				{
					return new Span<T>((T[])_object, _index, _length & 0x7FFFFFFF);
				}
				result = default(Span<T>);
				return result;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Memory(T[] array)
		{
			if (array == null)
			{
				this = default(Memory<T>);
				return;
			}
			if (default(T) == null && array.GetType() != typeof(T[]))
			{
				System.ThrowHelper.ThrowArrayTypeMismatchException();
			}
			_object = array;
			_index = 0;
			_length = array.Length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal Memory(T[] array, int start)
		{
			if (array == null)
			{
				if (start != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException();
				}
				this = default(Memory<T>);
				return;
			}
			if (default(T) == null && array.GetType() != typeof(T[]))
			{
				System.ThrowHelper.ThrowArrayTypeMismatchException();
			}
			if ((uint)start > (uint)array.Length)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException();
			}
			_object = array;
			_index = start;
			_length = array.Length - start;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Memory(T[] array, int start, int length)
		{
			if (array == null)
			{
				if (start != 0 || length != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException();
				}
				this = default(Memory<T>);
				return;
			}
			if (default(T) == null && array.GetType() != typeof(T[]))
			{
				System.ThrowHelper.ThrowArrayTypeMismatchException();
			}
			if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException();
			}
			_object = array;
			_index = start;
			_length = length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal Memory(MemoryManager<T> manager, int length)
		{
			if (length < 0)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException();
			}
			_object = manager;
			_index = int.MinValue;
			_length = length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal Memory(MemoryManager<T> manager, int start, int length)
		{
			if (length < 0 || start < 0)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException();
			}
			_object = manager;
			_index = start | int.MinValue;
			_length = length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal Memory(object obj, int start, int length)
		{
			_object = obj;
			_index = start;
			_length = length;
		}

		public static implicit operator Memory<T>(T[] array)
		{
			return new Memory<T>(array);
		}

		public static implicit operator Memory<T>(ArraySegment<T> segment)
		{
			return new Memory<T>(segment.Array, segment.Offset, segment.Count);
		}

		public static implicit operator ReadOnlyMemory<T>(Memory<T> memory)
		{
			return Unsafe.As<Memory<T>, ReadOnlyMemory<T>>(ref memory);
		}

		public override string ToString()
		{
			if (typeof(T) == typeof(char))
			{
				if (!(_object is string text))
				{
					return Span.ToString();
				}
				return text.Substring(_index, _length & 0x7FFFFFFF);
			}
			return $"System.Memory<{typeof(T).Name}>[{_length & 0x7FFFFFFF}]";
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Memory<T> Slice(int start)
		{
			int length = _length;
			int num = length & 0x7FFFFFFF;
			if ((uint)start > (uint)num)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new Memory<T>(_object, _index + start, length - start);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Memory<T> Slice(int start, int length)
		{
			int length2 = _length;
			int num = length2 & 0x7FFFFFFF;
			if ((uint)start > (uint)num || (uint)length > (uint)(num - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException();
			}
			return new Memory<T>(_object, _index + start, length | (length2 & int.MinValue));
		}

		public void CopyTo(Memory<T> destination)
		{
			Span.CopyTo(destination.Span);
		}

		public bool TryCopyTo(Memory<T> destination)
		{
			return Span.TryCopyTo(destination.Span);
		}

		public unsafe MemoryHandle Pin()
		{
			if (_index < 0)
			{
				return ((MemoryManager<T>)_object).Pin(_index & 0x7FFFFFFF);
			}
			if (typeof(T) == typeof(char) && _object is string value)
			{
				GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned);
				void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
				return new MemoryHandle(pointer, handle);
			}
			if (_object is T[] array)
			{
				if (_length < 0)
				{
					void* pointer2 = Unsafe.Add<T>(Unsafe.AsPointer(ref MemoryMarshal.GetReference<T>(array)), _index);
					return new MemoryHandle(pointer2);
				}
				GCHandle handle2 = GCHandle.Alloc(array, GCHandleType.Pinned);
				void* pointer3 = Unsafe.Add<T>((void*)handle2.AddrOfPinnedObject(), _index);
				return new MemoryHandle(pointer3, handle2);
			}
			return default(MemoryHandle);
		}

		public T[] ToArray()
		{
			return Span.ToArray();
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public override bool Equals(object obj)
		{
			if (obj is ReadOnlyMemory<T> readOnlyMemory)
			{
				return readOnlyMemory.Equals(this);
			}
			if (obj is Memory<T> other)
			{
				return Equals(other);
			}
			return false;
		}

		public bool Equals(Memory<T> other)
		{
			if (_object == other._object && _index == other._index)
			{
				return _length == other._length;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public override int GetHashCode()
		{
			if (_object == null)
			{
				return 0;
			}
			int hashCode = _object.GetHashCode();
			int index = _index;
			int hashCode2 = index.GetHashCode();
			index = _length;
			return CombineHashCodes(hashCode, hashCode2, index.GetHashCode());
		}

		private static int CombineHashCodes(int left, int right)
		{
			return ((left << 5) + left) ^ right;
		}

		private static int CombineHashCodes(int h1, int h2, int h3)
		{
			return CombineHashCodes(CombineHashCodes(h1, h2), h3);
		}
	}
	internal sealed class MemoryDebugView<T>
	{
		private readonly ReadOnlyMemory<T> _memory;

		[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		public T[] Items => _memory.ToArray();

		public MemoryDebugView(Memory<T> memory)
		{
			_memory = memory;
		}

		public MemoryDebugView(ReadOnlyMemory<T> memory)
		{
			_memory = memory;
		}
	}
	public static class MemoryExtensions
	{
		internal static readonly IntPtr StringAdjustment = MeasureStringAdjustment();

		public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span)
		{
			return span.TrimStart().TrimEnd();
		}

		public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span)
		{
			int i;
			for (i = 0; i < span.Length && char.IsWhiteSpace(span[i]); i++)
			{
			}
			return span.Slice(i);
		}

		public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span)
		{
			int num = span.Length - 1;
			while (num >= 0 && char.IsWhiteSpace(span[num]))
			{
				num--;
			}
			return span.Slice(0, num + 1);
		}

		public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, char trimChar)
		{
			return span.TrimStart(trimChar).TrimEnd(trimChar);
		}

		public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, char trimChar)
		{
			int i;
			for (i = 0; i < span.Length && span[i] == trimChar; i++)
			{
			}
			return span.Slice(i);
		}

		public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, char trimChar)
		{
			int num = span.Length - 1;
			while (num >= 0 && span[num] == trimChar)
			{
				num--;
			}
			return span.Slice(0, num + 1);
		}

		public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
		{
			return span.TrimStart(trimChars).TrimEnd(trimChars);
		}

		public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
		{
			if (trimChars.IsEmpty)
			{
				return span.TrimStart();
			}
			int i;
			for (i = 0; i < span.Length; i++)
			{
				int num = 0;
				while (num < trimChars.Length)
				{
					if (span[i] != trimChars[num])
					{
						num++;
						continue;
					}
					goto IL_003c;
				}
				break;
				IL_003c:;
			}
			return span.Slice(i);
		}

		public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
		{
			if (trimChars.IsEmpty)
			{
				return span.TrimEnd();
			}
			int num;
			for (num = span.Length - 1; num >= 0; num--)
			{
				int num2 = 0;
				while (num2 < trimChars.Length)
				{
					if (span[num] != trimChars[num2])
					{
						num2++;
						continue;
					}
					goto IL_0044;
				}
				break;
				IL_0044:;
			}
			return span.Slice(0, num + 1);
		}

		public static bool IsWhiteSpace(this ReadOnlySpan<char> span)
		{
			for (int i = 0; i < span.Length; i++)
			{
				if (!char.IsWhiteSpace(span[i]))
				{
					return false;
				}
			}
			return true;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOf<T>(this Span<T> span, T value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length);
			}
			if (typeof(T) == typeof(char))
			{
				return System.SpanHelpers.IndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length);
			}
			return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOf<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length);
			}
			return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOf<T>(this Span<T> span, T value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length);
			}
			if (typeof(T) == typeof(char))
			{
				return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length);
			}
			return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOf<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length);
			}
			return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool SequenceEqual<T>(this Span<T> span, ReadOnlySpan<T> other) where T : IEquatable<T>
		{
			int length = span.Length;
			if (default(T) != null && IsTypeComparableAsBytes<T>(out var size))
			{
				if (length == other.Length)
				{
					return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), (NUInt)length * size);
				}
				return false;
			}
			if (length == other.Length)
			{
				return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
			}
			return false;
		}

		public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other) where T : IComparable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.SequenceCompareTo(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 System.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 System.SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOf<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length);
			}
			if (typeof(T) == typeof(char))
			{
				return System.SpanHelpers.IndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length);
			}
			return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length);
			}
			return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOf<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value), span.Length);
			}
			if (typeof(T) == typeof(char))
			{
				return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, char>(ref value), span.Length);
			}
			return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOf<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOf(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), value.Length);
			}
			return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOfAny<T>(this Span<T> span, T value0, T value1) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length);
			}
			return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOfAny<T>(this Span<T> span, T value0, T value1, T value2) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length);
			}
			return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length);
			}
			return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length);
			}
			return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length);
			}
			return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int IndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.IndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length);
			}
			return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOfAny<T>(this Span<T> span, T value0, T value1) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length);
			}
			return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOfAny<T>(this Span<T> span, T value0, T value1, T value2) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length);
			}
			return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length);
			}
			return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), span.Length);
			}
			return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, T value0, T value1, T value2) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), Unsafe.As<T, byte>(ref value0), Unsafe.As<T, byte>(ref value1), Unsafe.As<T, byte>(ref value2), span.Length);
			}
			return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int LastIndexOfAny<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)), values.Length);
			}
			return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IEquatable<T>
		{
			int length = span.Length;
			if (default(T) != null && IsTypeComparableAsBytes<T>(out var size))
			{
				if (length == other.Length)
				{
					return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), (NUInt)length * size);
				}
				return false;
			}
			if (length == other.Length)
			{
				return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other) where T : IComparable<T>
		{
			if (typeof(T) == typeof(byte))
			{
				return System.SpanHelpers.SequenceCompareTo(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 System.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 System.SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool StartsWith<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			int length = value.Length;
			if (default(T) != null && IsTypeComparableAsBytes<T>(out var size))
			{
				if (length <= span.Length)
				{
					return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (NUInt)length * size);
				}
				return false;
			}
			if (length <= span.Length)
			{
				return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), length);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool StartsWith<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			int length = value.Length;
			if (default(T) != null && IsTypeComparableAsBytes<T>(out var size))
			{
				if (length <= span.Length)
				{
					return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (NUInt)length * size);
				}
				return false;
			}
			if (length <= span.Length)
			{
				return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), length);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool EndsWith<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			int length = span.Length;
			int length2 = value.Length;
			if (default(T) != null && IsTypeComparableAsBytes<T>(out var size))
			{
				if (length2 <= length)
				{
					return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (NUInt)length2 * size);
				}
				return false;
			}
			if (length2 <= length)
			{
				return System.SpanHelpers.SequenceEqual(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2), ref MemoryMarshal.GetReference(value), length2);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool EndsWith<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>
		{
			int length = span.Length;
			int length2 = value.Length;
			if (default(T) != null && IsTypeComparableAsBytes<T>(out var size))
			{
				if (length2 <= length)
				{
					return System.SpanHelpers.SequenceEqual(ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), (NUInt)length2 * size);
				}
				return false;
			}
			if (length2 <= length)
			{
				return System.SpanHelpers.SequenceEqual(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2), ref MemoryMarshal.GetReference(value), length2);
			}
			return false;
		}

		public static void Reverse<T>(this Span<T> span)
		{
			ref T reference = ref MemoryMarshal.GetReference(span);
			int num = 0;
			int num2 = span.Length - 1;
			while (num < num2)
			{
				T val = Unsafe.Add(ref reference, num);
				Unsafe.Add(ref reference, num) = Unsafe.Add(ref reference, num2);
				Unsafe.Add(ref reference, num2) = val;
				num++;
				num2--;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Span<T> AsSpan<T>(this T[] array)
		{
			return new Span<T>(array);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Span<T> AsSpan<T>(this T[] array, int start, int length)
		{
			return new Span<T>(array, start, length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Span<T> AsSpan<T>(this ArraySegment<T> segment)
		{
			return new Span<T>(segment.Array, segment.Offset, segment.Count);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start)
		{
			if ((uint)start > segment.Count)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new Span<T>(segment.Array, segment.Offset + start, segment.Count - start);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start, int length)
		{
			if ((uint)start > segment.Count)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			if ((uint)length > segment.Count - start)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length);
			}
			return new Span<T>(segment.Array, segment.Offset + start, length);
		}

		public static Memory<T> AsMemory<T>(this T[] array)
		{
			return new Memory<T>(array);
		}

		public static Memory<T> AsMemory<T>(this T[] array, int start)
		{
			return new Memory<T>(array, start);
		}

		public static Memory<T> AsMemory<T>(this T[] array, int start, int length)
		{
			return new Memory<T>(array, start, length);
		}

		public static Memory<T> AsMemory<T>(this ArraySegment<T> segment)
		{
			return new Memory<T>(segment.Array, segment.Offset, segment.Count);
		}

		public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start)
		{
			if ((uint)start > segment.Count)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new Memory<T>(segment.Array, segment.Offset + start, segment.Count - start);
		}

		public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start, int length)
		{
			if ((uint)start > segment.Count)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			if ((uint)length > segment.Count - start)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length);
			}
			return new Memory<T>(segment.Array, segment.Offset + start, length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void CopyTo<T>(this T[] source, Span<T> destination)
		{
			new ReadOnlySpan<T>(source).CopyTo(destination);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void CopyTo<T>(this T[] source, Memory<T> destination)
		{
			source.CopyTo(destination.Span);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other)
		{
			return ((ReadOnlySpan<T>)span).Overlaps(other);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other, out int elementOffset)
		{
			return ((ReadOnlySpan<T>)span).Overlaps(other, out elementOffset);
		}

		public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
		{
			if (span.IsEmpty || other.IsEmpty)
			{
				return false;
			}
			IntPtr intPtr = Unsafe.ByteOffset(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other));
			if (Unsafe.SizeOf<IntPtr>() == 4)
			{
				if ((uint)(int)intPtr >= (uint)(span.Length * Unsafe.SizeOf<T>()))
				{
					return (uint)(int)intPtr > (uint)(-(other.Length * Unsafe.SizeOf<T>()));
				}
				return true;
			}
			if ((ulong)(long)intPtr >= (ulong)((long)span.Length * (long)Unsafe.SizeOf<T>()))
			{
				return (ulong)(long)intPtr > (ulong)(-((long)other.Length * (long)Unsafe.SizeOf<T>()));
			}
			return true;
		}

		public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other, out int elementOffset)
		{
			if (span.IsEmpty || other.IsEmpty)
			{
				elementOffset = 0;
				return false;
			}
			IntPtr intPtr = Unsafe.ByteOffset(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other));
			if (Unsafe.SizeOf<IntPtr>() == 4)
			{
				if ((uint)(int)intPtr < (uint)(span.Length * Unsafe.SizeOf<T>()) || (uint)(int)intPtr > (uint)(-(other.Length * Unsafe.SizeOf<T>())))
				{
					if ((int)intPtr % Unsafe.SizeOf<T>() != 0)
					{
						System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch();
					}
					elementOffset = (int)intPtr / Unsafe.SizeOf<T>();
					return true;
				}
				elementOffset = 0;
				return false;
			}
			if ((ulong)(long)intPtr < (ulong)((long)span.Length * (long)Unsafe.SizeOf<T>()) || (ulong)(long)intPtr > (ulong)(-((long)other.Length * (long)Unsafe.SizeOf<T>())))
			{
				if ((long)intPtr % Unsafe.SizeOf<T>() != 0L)
				{
					System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch();
				}
				elementOffset = (int)((long)intPtr / Unsafe.SizeOf<T>());
				return true;
			}
			elementOffset = 0;
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T>(this Span<T> span, IComparable<T> comparable)
		{
			return span.BinarySearch<T, IComparable<T>>(comparable);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T, TComparable>(this Span<T> span, TComparable comparable) where TComparable : IComparable<T>
		{
			return BinarySearch((ReadOnlySpan<T>)span, comparable);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T, TComparer>(this Span<T> span, T value, TComparer comparer) where TComparer : IComparer<T>
		{
			return ((ReadOnlySpan<T>)span).BinarySearch(value, comparer);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T>(this ReadOnlySpan<T> span, IComparable<T> comparable)
		{
			return MemoryExtensions.BinarySearch<T, IComparable<T>>(span, comparable);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T, TComparable>(this ReadOnlySpan<T> span, TComparable comparable) where TComparable : IComparable<T>
		{
			return System.SpanHelpers.BinarySearch(span, comparable);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T, TComparer>(this ReadOnlySpan<T> span, T value, TComparer comparer) where TComparer : IComparer<T>
		{
			if (comparer == null)
			{
				System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.comparer);
			}
			System.SpanHelpers.ComparerComparable<T, TComparer> comparable = new System.SpanHelpers.ComparerComparable<T, TComparer>(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 = (NUInt)1;
				return true;
			}
			if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort))
			{
				size = (NUInt)2;
				return true;
			}
			if (typeof(T) == typeof(int) || typeof(T) == typeof(uint))
			{
				size = (NUInt)4;
				return true;
			}
			if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong))
			{
				size = (NUInt)8;
				return true;
			}
			size = default(NUInt);
			return false;
		}

		public static Span<T> AsSpan<T>(this T[] array, int start)
		{
			return Span<T>.Create(array, start);
		}

		public static bool Contains(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
		{
			return span.IndexOf(value, comparisonType) >= 0;
		}

		public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType)
		{
			switch (comparisonType)
			{
			case StringComparison.Ordinal:
				return span.SequenceEqual(other);
			case StringComparison.OrdinalIgnoreCase:
				if (span.Length != other.Length)
				{
					return false;
				}
				return EqualsOrdinalIgnoreCase(span, other);
			default:
				return span.ToString().Equals(other.ToString(), comparisonType);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool EqualsOrdinalIgnoreCase(ReadOnlySpan<char> span, ReadOnlySpan<char> other)
		{
			if (other.Length == 0)
			{
				return true;
			}
			return CompareToOrdinalIgnoreCase(span, other) == 0;
		}

		public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType)
		{
			return comparisonType switch
			{
				StringComparison.Ordinal => span.SequenceCompareTo(other), 
				StringComparison.OrdinalIgnoreCase => CompareToOrdinalIgnoreCase(span, other), 
				_ => string.Compare(span.ToString(), other.ToString(), comparisonType), 
			};
		}

		private unsafe static int CompareToOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
		{
			int num = Math.Min(strA.Length, strB.Length);
			int num2 = num;
			fixed (char* ptr = &MemoryMarshal.GetReference(strA))
			{
				fixed (char* ptr3 = &MemoryMarshal.GetReference(strB))
				{
					char* ptr2 = ptr;
					char* ptr4 = ptr3;
					while (num != 0 && *ptr2 <= '\u007f' && *ptr4 <= '\u007f')
					{
						int num3 = *ptr2;
						int num4 = *ptr4;
						if (num3 == num4)
						{
							ptr2++;
							ptr4++;
							num--;
							continue;
						}
						if ((uint)(num3 - 97) <= 25u)
						{
							num3 -= 32;
						}
						if ((uint)(num4 - 97) <= 25u)
						{
							num4 -= 32;
						}
						if (num3 != num4)
						{
							return num3 - num4;
						}
						ptr2++;
						ptr4++;
						num--;
					}
					if (num == 0)
					{
						return strA.Length - strB.Length;
					}
					num2 -= num;
					return string.Compare(strA.Slice(num2).ToString(), strB.Slice(num2).ToString(), StringComparison.OrdinalIgnoreCase);
				}
			}
		}

		public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
		{
			if (comparisonType == StringComparison.Ordinal)
			{
				return span.IndexOf(value);
			}
			return span.ToString().IndexOf(value.ToString(), comparisonType);
		}

		public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo culture)
		{
			if (culture == null)
			{
				System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.culture);
			}
			if (destination.Length < source.Length)
			{
				return -1;
			}
			string text = source.ToString();
			string text2 = text.ToLower(culture);
			AsSpan(text2).CopyTo(destination);
			return source.Length;
		}

		public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination)
		{
			return source.ToLower(destination, CultureInfo.InvariantCulture);
		}

		public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo culture)
		{
			if (culture == null)
			{
				System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.culture);
			}
			if (destination.Length < source.Length)
			{
				return -1;
			}
			string text = source.ToString();
			string text2 = text.ToUpper(culture);
			AsSpan(text2).CopyTo(destination);
			return source.Length;
		}

		public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination)
		{
			return source.ToUpper(destination, CultureInfo.InvariantCulture);
		}

		public static bool EndsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
		{
			switch (comparisonType)
			{
			case StringComparison.Ordinal:
				return span.EndsWith(value);
			case StringComparison.OrdinalIgnoreCase:
				if (value.Length <= span.Length)
				{
					return EqualsOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value);
				}
				return false;
			default:
			{
				string text = span.ToString();
				string value2 = value.ToString();
				return text.EndsWith(value2, comparisonType);
			}
			}
		}

		public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
		{
			switch (comparisonType)
			{
			case StringComparison.Ordinal:
				return span.StartsWith(value);
			case StringComparison.OrdinalIgnoreCase:
				if (value.Length <= span.Length)
				{
					return EqualsOrdinalIgnoreCase(span.Slice(0, value.Length), value);
				}
				return false;
			default:
			{
				string text = span.ToString();
				string value2 = value.ToString();
				return text.StartsWith(value2, comparisonType);
			}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ReadOnlySpan<char> AsSpan(this string text)
		{
			if (text == null)
			{
				return default(ReadOnlySpan<char>);
			}
			return new ReadOnlySpan<char>(Unsafe.As<Pinnable<char>>(text), StringAdjustment, text.Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ReadOnlySpan<char> AsSpan(this string text, int start)
		{
			if (text == null)
			{
				if (start != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				return default(ReadOnlySpan<char>);
			}
			if ((uint)start > (uint)text.Length)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new ReadOnlySpan<char>(Unsafe.As<Pinnable<char>>(text), StringAdjustment + start * 2, text.Length - start);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ReadOnlySpan<char> AsSpan(this string text, int start, int length)
		{
			if (text == null)
			{
				if (start != 0 || length != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				return default(ReadOnlySpan<char>);
			}
			if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new ReadOnlySpan<char>(Unsafe.As<Pinnable<char>>(text), StringAdjustment + start * 2, length);
		}

		public static ReadOnlyMemory<char> AsMemory(this string text)
		{
			if (text == null)
			{
				return default(ReadOnlyMemory<char>);
			}
			return new ReadOnlyMemory<char>(text, 0, text.Length);
		}

		public static ReadOnlyMemory<char> AsMemory(this string text, int start)
		{
			if (text == null)
			{
				if (start != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				return default(ReadOnlyMemory<char>);
			}
			if ((uint)start > (uint)text.Length)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new ReadOnlyMemory<char>(text, start, text.Length - start);
		}

		public static ReadOnlyMemory<char> AsMemory(this string text, int start, int length)
		{
			if (text == null)
			{
				if (start != 0 || length != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				return default(ReadOnlyMemory<char>);
			}
			if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new ReadOnlyMemory<char>(text, start, length);
		}

		private unsafe static IntPtr MeasureStringAdjustment()
		{
			string text = "a";
			fixed (char* source = text)
			{
				return Unsafe.ByteOffset(ref Unsafe.As<Pinnable<char>>(text).Data, ref Unsafe.AsRef<char>(source));
			}
		}
	}
	[DebuggerTypeProxy(typeof(System.MemoryDebugView<>))]
	[DebuggerDisplay("{ToString(),raw}")]
	public readonly struct ReadOnlyMemory<T>
	{
		private readonly object _object;

		private readonly int _index;

		private readonly int _length;

		internal const int RemoveFlagsBitMask = int.MaxValue;

		public static ReadOnlyMemory<T> Empty => default(ReadOnlyMemory<T>);

		public int Length => _length & 0x7FFFFFFF;

		public bool IsEmpty => (_length & 0x7FFFFFFF) == 0;

		public ReadOnlySpan<T> Span
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				if (_index < 0)
				{
					return ((MemoryManager<T>)_object).GetSpan().Slice(_index & 0x7FFFFFFF, _length);
				}
				ReadOnlySpan<T> result;
				if (typeof(T) == typeof(char) && _object is string text)
				{
					result = new ReadOnlySpan<T>(Unsafe.As<Pinnable<T>>(text), MemoryExtensions.StringAdjustment, text.Length);
					return result.Slice(_index, _length);
				}
				if (_object != null)
				{
					return new ReadOnlySpan<T>((T[])_object, _index, _length & 0x7FFFFFFF);
				}
				result = default(ReadOnlySpan<T>);
				return result;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlyMemory(T[] array)
		{
			if (array == null)
			{
				this = default(ReadOnlyMemory<T>);
				return;
			}
			_object = array;
			_index = 0;
			_length = array.Length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlyMemory(T[] array, int start, int length)
		{
			if (array == null)
			{
				if (start != 0 || length != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException();
				}
				this = default(ReadOnlyMemory<T>);
				return;
			}
			if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException();
			}
			_object = array;
			_index = start;
			_length = length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal ReadOnlyMemory(object obj, int start, int length)
		{
			_object = obj;
			_index = start;
			_length = length;
		}

		public static implicit operator ReadOnlyMemory<T>(T[] array)
		{
			return new ReadOnlyMemory<T>(array);
		}

		public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> segment)
		{
			return new ReadOnlyMemory<T>(segment.Array, segment.Offset, segment.Count);
		}

		public override string ToString()
		{
			if (typeof(T) == typeof(char))
			{
				if (!(_object is string text))
				{
					return Span.ToString();
				}
				return text.Substring(_index, _length & 0x7FFFFFFF);
			}
			return $"System.ReadOnlyMemory<{typeof(T).Name}>[{_length & 0x7FFFFFFF}]";
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlyMemory<T> Slice(int start)
		{
			int length = _length;
			int num = length & 0x7FFFFFFF;
			if ((uint)start > (uint)num)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new ReadOnlyMemory<T>(_object, _index + start, length - start);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlyMemory<T> Slice(int start, int length)
		{
			int length2 = _length;
			int num = _length & 0x7FFFFFFF;
			if ((uint)start > (uint)num || (uint)length > (uint)(num - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			return new ReadOnlyMemory<T>(_object, _index + start, length | (length2 & int.MinValue));
		}

		public void CopyTo(Memory<T> destination)
		{
			Span.CopyTo(destination.Span);
		}

		public bool TryCopyTo(Memory<T> destination)
		{
			return Span.TryCopyTo(destination.Span);
		}

		public unsafe MemoryHandle Pin()
		{
			if (_index < 0)
			{
				return ((MemoryManager<T>)_object).Pin(_index & 0x7FFFFFFF);
			}
			if (typeof(T) == typeof(char) && _object is string value)
			{
				GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned);
				void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
				return new MemoryHandle(pointer, handle);
			}
			if (_object is T[] array)
			{
				if (_length < 0)
				{
					void* pointer2 = Unsafe.Add<T>(Unsafe.AsPointer(ref MemoryMarshal.GetReference<T>(array)), _index);
					return new MemoryHandle(pointer2);
				}
				GCHandle handle2 = GCHandle.Alloc(array, GCHandleType.Pinned);
				void* pointer3 = Unsafe.Add<T>((void*)handle2.AddrOfPinnedObject(), _index);
				return new MemoryHandle(pointer3, handle2);
			}
			return default(MemoryHandle);
		}

		public T[] ToArray()
		{
			return Span.ToArray();
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public override bool Equals(object obj)
		{
			if (obj is ReadOnlyMemory<T> other)
			{
				return Equals(other);
			}
			if (obj is Memory<T> memory)
			{
				return Equals(memory);
			}
			return false;
		}

		public bool Equals(ReadOnlyMemory<T> other)
		{
			if (_object == other._object && _index == other._index)
			{
				return _length == other._length;
			}
			return false;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public override int GetHashCode()
		{
			if (_object == null)
			{
				return 0;
			}
			int hashCode = _object.GetHashCode();
			int index = _index;
			int hashCode2 = index.GetHashCode();
			index = _length;
			return CombineHashCodes(hashCode, hashCode2, index.GetHashCode());
		}

		private static int CombineHashCodes(int left, int right)
		{
			return ((left << 5) + left) ^ right;
		}

		private static int CombineHashCodes(int h1, int h2, int h3)
		{
			return CombineHashCodes(CombineHashCodes(h1, h2), h3);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal object GetObjectStartLength(out int start, out int length)
		{
			start = _index;
			length = _length;
			return _object;
		}
	}
	[DebuggerTypeProxy(typeof(System.SpanDebugView<>))]
	[DebuggerDisplay("{ToString(),raw}")]
	[DebuggerTypeProxy(typeof(System.SpanDebugView<>))]
	[DebuggerDisplay("{ToString(),raw}")]
	public readonly ref struct ReadOnlySpan<T>
	{
		public ref struct Enumerator
		{
			private readonly ReadOnlySpan<T> _span;

			private int _index;

			public ref readonly T Current
			{
				[MethodImpl(MethodImplOptions.AggressiveInlining)]
				get
				{
					return ref _span[_index];
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			internal Enumerator(ReadOnlySpan<T> span)
			{
				_span = span;
				_index = -1;
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			public bool MoveNext()
			{
				int num = _index + 1;
				if (num < _span.Length)
				{
					_index = num;
					return true;
				}
				return false;
			}
		}

		private readonly Pinnable<T> _pinnable;

		private readonly IntPtr _byteOffset;

		private readonly int _length;

		public int Length => _length;

		public bool IsEmpty => _length == 0;

		public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>);

		public unsafe ref readonly T this[int index]
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				if ((uint)index >= (uint)_length)
				{
					System.ThrowHelper.ThrowIndexOutOfRangeException();
				}
				if (_pinnable == null)
				{
					IntPtr byteOffset = _byteOffset;
					return ref Unsafe.Add(ref Unsafe.AsRef<T>(byteOffset.ToPointer()), index);
				}
				return ref Unsafe.Add(ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset), index);
			}
		}

		internal Pinnable<T> Pinnable => _pinnable;

		internal IntPtr ByteOffset => _byteOffset;

		public static bool operator !=(ReadOnlySpan<T> left, ReadOnlySpan<T> right)
		{
			return !(left == right);
		}

		[Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public override bool Equals(object obj)
		{
			throw new NotSupportedException(System.SR.NotSupported_CannotCallEqualsOnSpan);
		}

		[Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public override int GetHashCode()
		{
			throw new NotSupportedException(System.SR.NotSupported_CannotCallGetHashCodeOnSpan);
		}

		public static implicit operator ReadOnlySpan<T>(T[] array)
		{
			return new ReadOnlySpan<T>(array);
		}

		public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment)
		{
			return new ReadOnlySpan<T>(segment.Array, segment.Offset, segment.Count);
		}

		public Enumerator GetEnumerator()
		{
			return new Enumerator(this);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlySpan(T[] array)
		{
			if (array == null)
			{
				this = default(ReadOnlySpan<T>);
				return;
			}
			_length = array.Length;
			_pinnable = Unsafe.As<Pinnable<T>>(array);
			_byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlySpan(T[] array, int start, int length)
		{
			if (array == null)
			{
				if (start != 0 || length != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				this = default(ReadOnlySpan<T>);
				return;
			}
			if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			_length = length;
			_pinnable = Unsafe.As<Pinnable<T>>(array);
			_byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment.Add<T>(start);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public unsafe ReadOnlySpan(void* pointer, int length)
		{
			if (System.SpanHelpers.IsReferenceOrContainsReferences<T>())
			{
				System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
			}
			if (length < 0)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			_length = length;
			_pinnable = null;
			_byteOffset = new IntPtr(pointer);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal ReadOnlySpan(Pinnable<T> pinnable, IntPtr byteOffset, int length)
		{
			_length = length;
			_pinnable = pinnable;
			_byteOffset = byteOffset;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public unsafe ref readonly T GetPinnableReference()
		{
			if (_length != 0)
			{
				if (_pinnable == null)
				{
					IntPtr byteOffset = _byteOffset;
					return ref Unsafe.AsRef<T>(byteOffset.ToPointer());
				}
				return ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset);
			}
			return ref Unsafe.AsRef<T>(null);
		}

		public void CopyTo(Span<T> destination)
		{
			if (!TryCopyTo(destination))
			{
				System.ThrowHelper.ThrowArgumentException_DestinationTooShort();
			}
		}

		public bool TryCopyTo(Span<T> destination)
		{
			int length = _length;
			int length2 = destination.Length;
			if (length == 0)
			{
				return true;
			}
			if ((uint)length > (uint)length2)
			{
				return false;
			}
			ref T src = ref DangerousGetPinnableReference();
			System.SpanHelpers.CopyTo(ref destination.DangerousGetPinnableReference(), length2, ref src, length);
			return true;
		}

		public static bool operator ==(ReadOnlySpan<T> left, ReadOnlySpan<T> right)
		{
			if (left._length == right._length)
			{
				return Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference());
			}
			return false;
		}

		public unsafe override string ToString()
		{
			if (typeof(T) == typeof(char))
			{
				if (_byteOffset == MemoryExtensions.StringAdjustment)
				{
					object obj = Unsafe.As<object>(_pinnable);
					if (obj is string text && _length == text.Length)
					{
						return text;
					}
				}
				fixed (char* value = &Unsafe.As<T, char>(ref DangerousGetPinnableReference()))
				{
					return new string(value, 0, _length);
				}
			}
			return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]";
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlySpan<T> Slice(int start)
		{
			if ((uint)start > (uint)_length)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			IntPtr byteOffset = _byteOffset.Add<T>(start);
			int length = _length - start;
			return new ReadOnlySpan<T>(_pinnable, byteOffset, length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public ReadOnlySpan<T> Slice(int start, int length)
		{
			if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			IntPtr byteOffset = _byteOffset.Add<T>(start);
			return new ReadOnlySpan<T>(_pinnable, byteOffset, length);
		}

		public T[] ToArray()
		{
			if (_length == 0)
			{
				return System.SpanHelpers.PerTypeValues<T>.EmptyArray;
			}
			T[] array = new T[_length];
			CopyTo(array);
			return array;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[EditorBrowsable(EditorBrowsableState.Never)]
		internal unsafe ref T DangerousGetPinnableReference()
		{
			if (_pinnable == null)
			{
				IntPtr byteOffset = _byteOffset;
				return ref Unsafe.AsRef<T>(byteOffset.ToPointer());
			}
			return ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset);
		}
	}
	[DebuggerTypeProxy(typeof(System.SpanDebugView<>))]
	[DebuggerDisplay("{ToString(),raw}")]
	[DebuggerTypeProxy(typeof(System.SpanDebugView<>))]
	[DebuggerDisplay("{ToString(),raw}")]
	public readonly ref struct Span<T>
	{
		public ref struct Enumerator
		{
			private readonly Span<T> _span;

			private int _index;

			public ref T Current
			{
				[MethodImpl(MethodImplOptions.AggressiveInlining)]
				get
				{
					return ref _span[_index];
				}
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			internal Enumerator(Span<T> span)
			{
				_span = span;
				_index = -1;
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			public bool MoveNext()
			{
				int num = _index + 1;
				if (num < _span.Length)
				{
					_index = num;
					return true;
				}
				return false;
			}
		}

		private readonly Pinnable<T> _pinnable;

		private readonly IntPtr _byteOffset;

		private readonly int _length;

		public int Length => _length;

		public bool IsEmpty => _length == 0;

		public static Span<T> Empty => default(Span<T>);

		public unsafe ref T this[int index]
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				if ((uint)index >= (uint)_length)
				{
					System.ThrowHelper.ThrowIndexOutOfRangeException();
				}
				if (_pinnable == null)
				{
					IntPtr byteOffset = _byteOffset;
					return ref Unsafe.Add(ref Unsafe.AsRef<T>(byteOffset.ToPointer()), index);
				}
				return ref Unsafe.Add(ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset), index);
			}
		}

		internal Pinnable<T> Pinnable => _pinnable;

		internal IntPtr ByteOffset => _byteOffset;

		public static bool operator !=(Span<T> left, Span<T> right)
		{
			return !(left == right);
		}

		[Obsolete("Equals() on Span will always throw an exception. Use == instead.")]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public override bool Equals(object obj)
		{
			throw new NotSupportedException(System.SR.NotSupported_CannotCallEqualsOnSpan);
		}

		[Obsolete("GetHashCode() on Span will always throw an exception.")]
		[EditorBrowsable(EditorBrowsableState.Never)]
		public override int GetHashCode()
		{
			throw new NotSupportedException(System.SR.NotSupported_CannotCallGetHashCodeOnSpan);
		}

		public static implicit operator Span<T>(T[] array)
		{
			return new Span<T>(array);
		}

		public static implicit operator Span<T>(ArraySegment<T> segment)
		{
			return new Span<T>(segment.Array, segment.Offset, segment.Count);
		}

		public Enumerator GetEnumerator()
		{
			return new Enumerator(this);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Span(T[] array)
		{
			if (array == null)
			{
				this = default(Span<T>);
				return;
			}
			if (default(T) == null && array.GetType() != typeof(T[]))
			{
				System.ThrowHelper.ThrowArrayTypeMismatchException();
			}
			_length = array.Length;
			_pinnable = Unsafe.As<Pinnable<T>>(array);
			_byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static Span<T> Create(T[] array, int start)
		{
			if (array == null)
			{
				if (start != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				return default(Span<T>);
			}
			if (default(T) == null && array.GetType() != typeof(T[]))
			{
				System.ThrowHelper.ThrowArrayTypeMismatchException();
			}
			if ((uint)start > (uint)array.Length)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			IntPtr byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment.Add<T>(start);
			int length = array.Length - start;
			return new Span<T>(Unsafe.As<Pinnable<T>>(array), byteOffset, length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Span(T[] array, int start, int length)
		{
			if (array == null)
			{
				if (start != 0 || length != 0)
				{
					System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
				}
				this = default(Span<T>);
				return;
			}
			if (default(T) == null && array.GetType() != typeof(T[]))
			{
				System.ThrowHelper.ThrowArrayTypeMismatchException();
			}
			if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			_length = length;
			_pinnable = Unsafe.As<Pinnable<T>>(array);
			_byteOffset = System.SpanHelpers.PerTypeValues<T>.ArrayAdjustment.Add<T>(start);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[CLSCompliant(false)]
		public unsafe Span(void* pointer, int length)
		{
			if (System.SpanHelpers.IsReferenceOrContainsReferences<T>())
			{
				System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
			}
			if (length < 0)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			_length = length;
			_pinnable = null;
			_byteOffset = new IntPtr(pointer);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal Span(Pinnable<T> pinnable, IntPtr byteOffset, int length)
		{
			_length = length;
			_pinnable = pinnable;
			_byteOffset = byteOffset;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public unsafe ref T GetPinnableReference()
		{
			if (_length != 0)
			{
				if (_pinnable == null)
				{
					IntPtr byteOffset = _byteOffset;
					return ref Unsafe.AsRef<T>(byteOffset.ToPointer());
				}
				return ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset);
			}
			return ref Unsafe.AsRef<T>(null);
		}

		public unsafe void Clear()
		{
			int length = _length;
			if (length == 0)
			{
				return;
			}
			UIntPtr byteLength = (UIntPtr)(ulong)((uint)length * Unsafe.SizeOf<T>());
			if ((Unsafe.SizeOf<T>() & (sizeof(IntPtr) - 1)) != 0)
			{
				if (_pinnable == null)
				{
					IntPtr byteOffset = _byteOffset;
					byte* ptr = (byte*)byteOffset.ToPointer();
					System.SpanHelpers.ClearLessThanPointerSized(ptr, byteLength);
				}
				else
				{
					System.SpanHelpers.ClearLessThanPointerSized(ref Unsafe.As<T, byte>(ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset)), byteLength);
				}
			}
			else if (System.SpanHelpers.IsReferenceOrContainsReferences<T>())
			{
				UIntPtr pointerSizeLength = (UIntPtr)(ulong)(length * Unsafe.SizeOf<T>() / sizeof(IntPtr));
				System.SpanHelpers.ClearPointerSizedWithReferences(ref Unsafe.As<T, IntPtr>(ref DangerousGetPinnableReference()), pointerSizeLength);
			}
			else
			{
				System.SpanHelpers.ClearPointerSizedWithoutReferences(ref Unsafe.As<T, byte>(ref DangerousGetPinnableReference()), byteLength);
			}
		}

		public unsafe void Fill(T value)
		{
			int length = _length;
			if (length == 0)
			{
				return;
			}
			if (Unsafe.SizeOf<T>() == 1)
			{
				byte value2 = Unsafe.As<T, byte>(ref value);
				if (_pinnable == null)
				{
					IntPtr byteOffset = _byteOffset;
					Unsafe.InitBlockUnaligned(byteOffset.ToPointer(), value2, (uint)length);
				}
				else
				{
					Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset)), value2, (uint)length);
				}
				return;
			}
			ref T source = ref DangerousGetPinnableReference();
			int i;
			for (i = 0; i < (length & -8); i += 8)
			{
				Unsafe.Add(ref source, i) = value;
				Unsafe.Add(ref source, i + 1) = value;
				Unsafe.Add(ref source, i + 2) = value;
				Unsafe.Add(ref source, i + 3) = value;
				Unsafe.Add(ref source, i + 4) = value;
				Unsafe.Add(ref source, i + 5) = value;
				Unsafe.Add(ref source, i + 6) = value;
				Unsafe.Add(ref source, i + 7) = value;
			}
			if (i < (length & -4))
			{
				Unsafe.Add(ref source, i) = value;
				Unsafe.Add(ref source, i + 1) = value;
				Unsafe.Add(ref source, i + 2) = value;
				Unsafe.Add(ref source, i + 3) = value;
				i += 4;
			}
			for (; i < length; i++)
			{
				Unsafe.Add(ref source, i) = value;
			}
		}

		public void CopyTo(Span<T> destination)
		{
			if (!TryCopyTo(destination))
			{
				System.ThrowHelper.ThrowArgumentException_DestinationTooShort();
			}
		}

		public bool TryCopyTo(Span<T> destination)
		{
			int length = _length;
			int length2 = destination._length;
			if (length == 0)
			{
				return true;
			}
			if ((uint)length > (uint)length2)
			{
				return false;
			}
			ref T src = ref DangerousGetPinnableReference();
			System.SpanHelpers.CopyTo(ref destination.DangerousGetPinnableReference(), length2, ref src, length);
			return true;
		}

		public static bool operator ==(Span<T> left, Span<T> right)
		{
			if (left._length == right._length)
			{
				return Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference());
			}
			return false;
		}

		public static implicit operator ReadOnlySpan<T>(Span<T> span)
		{
			return new ReadOnlySpan<T>(span._pinnable, span._byteOffset, span._length);
		}

		public unsafe override string ToString()
		{
			if (typeof(T) == typeof(char))
			{
				fixed (char* value = &Unsafe.As<T, char>(ref DangerousGetPinnableReference()))
				{
					return new string(value, 0, _length);
				}
			}
			return $"System.Span<{typeof(T).Name}>[{_length}]";
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Span<T> Slice(int start)
		{
			if ((uint)start > (uint)_length)
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			IntPtr byteOffset = _byteOffset.Add<T>(start);
			int length = _length - start;
			return new Span<T>(_pinnable, byteOffset, length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Span<T> Slice(int start, int length)
		{
			if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
			{
				System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start);
			}
			IntPtr byteOffset = _byteOffset.Add<T>(start);
			return new Span<T>(_pinnable, byteOffset, length);
		}

		public T[] ToArray()
		{
			if (_length == 0)
			{
				return System.SpanHelpers.PerTypeValues<T>.EmptyArray;
			}
			T[] array = new T[_length];
			CopyTo(array);
			return array;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[EditorBrowsable(EditorBrowsableState.Never)]
		internal unsafe ref T DangerousGetPinnableReference()
		{
			if (_pinnable == null)
			{
				IntPtr byteOffset = _byteOffset;
				return ref Unsafe.AsRef<T>(byteOffset.ToPointer());
			}
			return ref Unsafe.AddByteOffset(ref _pinnable.Data, _byteOffset);
		}
	}
	internal sealed class SpanDebugView<T>
	{
		private readonly T[] _array;

		[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		public T[] Items => _array;

		public SpanDebugView(Span<T> span)
		{
			_array = span.ToArray();
		}

		public SpanDebugView(ReadOnlySpan<T> span)
		{
			_array = span.ToArray();
		}
	}
	internal static class SpanHelpers
	{
		internal struct ComparerComparable<T, TComparer> : IComparable<T> where TComparer : IComparer<T>
		{
			private readonly T _value;

			private readonly TComparer _comparer;

			public ComparerComparable(T value, TComparer comparer)
			{
				_value = value;
				_comparer = comparer;
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			public int CompareTo(T other)
			{
				return _comparer.Compare(_value, other);
			}
		}

		[StructLayout(LayoutKind.Sequential, Size = 64)]
		private struct Reg64
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 32)]
		private struct Reg32
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 16)]
		private struct Reg16
		{
		}

		public static class PerTypeValues<T>
		{
			public static readonly bool IsReferenceOrContainsReferences = IsReferenceOrContainsReferencesCore(typeof(T));

			public static readonly T[] EmptyArray = new T[0];

			public static readonly IntPtr ArrayAdjustment = MeasureArrayAdjustment();

			private static IntPtr MeasureArrayAdjustment()
			{
				T[] array = new T[1];
				return Unsafe.ByteOffset(ref Unsafe.As<Pinnable<T>>(array).Data, ref array[0]);
			}
		}

		private const ulong XorPowerOfTwoToHighByte = 283686952306184uL;

		private const ulong XorPowerOfTwoToHighChar = 4295098372uL;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int BinarySearch<T, TComparable>(this ReadOnlySpan<T> span, TComparable comparable) where TComparable : IComparable<T>
		{
			if (comparable == null)
			{
				System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.comparable);
			}
			return BinarySearch(ref MemoryMarshal.GetReference(span), span.Length, comparable);
		}

		public static int BinarySearch<T, TComparable>(ref T spanStart, int length, TComparable comparable) where TComparable : IComparable<T>
		{
			int num = 0;
			int num2 = length - 1;
			while (num <= num2)
			{
				int num3 = num2 + num >>> 1;
				int num4 = comparable.CompareTo(Unsafe.Add(ref spanStart, num3));
				if (num4 == 0)
				{
					return num3;
				}
				if (num4 > 0)
				{
					num = num3 + 1;
				}
				else
				{
					num2 = num3 - 1;
				}
			}
			return ~num;
		}

		public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
		{
			if (valueLength == 0)
			{
				return 0;
			}
			byte value2 = value;
			ref byte second = ref Unsafe.Add(ref value, 1);
			int num = valueLength - 1;
			int num2 = 0;
			while (true)
			{
				int num3 = searchSpaceLength - num2 - num;
				if (num3 <= 0)
				{
					break;
				}
				int num4 = IndexOf(ref Unsafe.Add(ref searchSpace, num2), value2, num3);
				if (num4 == -1)
				{
					break;
				}
				num2 += num4;
				if (SequenceEqual(ref Unsafe.Add(ref searchSpace, num2 + 1), ref second, num))
				{
					return num2;
				}
				num2++;
			}
			return -1;
		}

		public static int IndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
		{
			if (valueLength == 0)
			{
				return 0;
			}
			int num = -1;
			for (int i = 0; i < valueLength; i++)
			{
				int num2 = IndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
				if ((uint)num2 < (uint)num)
				{
					num = num2;
					searchSpaceLength = num2;
					if (num == 0)
					{
						break;
					}
				}
			}
			return num;
		}

		public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
		{
			if (valueLength == 0)
			{
				return 0;
			}
			int num = -1;
			for (int i = 0; i < valueLength; i++)
			{
				int num2 = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
				if (num2 > num)
				{
					num = num2;
				}
			}
			return num;
		}

		public unsafe static int IndexOf(ref byte searchSpace, byte value, int length)
		{
			IntPtr intPtr = (IntPtr)0;
			IntPtr intPtr2 = (IntPtr)length;
			if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
			{
				int num = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
				intPtr2 = (IntPtr)((Vector<byte>.Count - num) & (Vector<byte>.Count - 1));
			}
			while (true)
			{
				if ((nuint)(void*)intPtr2 >= (nuint)8u)
				{
					intPtr2 -= 8;
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr))
					{
						goto IL_0242;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 1))
					{
						goto IL_024a;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 2))
					{
						goto IL_0258;
					}
					if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 3))
					{
						if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 4))
						{
							if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 5))
							{
								if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 6))
								{
									if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 7))
									{
										break;
									}
									intPtr += 8;
									continue;
								}
								return (int)(void*)(intPtr + 6);
							}
							return (int)(void*)(intPtr + 5);
						}
						return (int)(void*)(intPtr + 4);
					}
					goto IL_0266;
				}
				if ((nuint)(void*)intPtr2 >= (nuint)4u)
				{
					intPtr2 -= 4;
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr))
					{
						goto IL_0242;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 1))
					{
						goto IL_024a;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 2))
					{
						goto IL_0258;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 3))
					{
						goto IL_0266;
					}
					intPtr += 4;
				}
				while ((void*)intPtr2 != null)
				{
					intPtr2 -= 1;
					if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr))
					{
						intPtr += 1;
						continue;
					}
					goto IL_0242;
				}
				if (Vector.IsHardwareAccelerated && (int)(void*)intPtr < length)
				{
					intPtr2 = (IntPtr)((length - (int)(void*)intPtr) & ~(Vector<byte>.Count - 1));
					Vector<byte> vector = GetVector(value);
					for (; (void*)intPtr2 > (void*)intPtr; intPtr += Vector<byte>.Count)
					{
						Vector<byte> vector2 = Vector.Equals(vector, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, intPtr)));
						if (!Vector<byte>.Zero.Equals(vector2))
						{
							return (int)(void*)intPtr + LocateFirstFoundByte(vector2);
						}
					}
					if ((int)(void*)intPtr < length)
					{
						intPtr2 = (IntPtr)(length - (int)(void*)intPtr);
						continue;
					}
				}
				return -1;
				IL_0266:
				return (int)(void*)(intPtr + 3);
				IL_0242:
				return (int)(void*)intPtr;
				IL_0258:
				return (int)(void*)(intPtr + 2);
				IL_024a:
				return (int)(void*)(intPtr + 1);
			}
			return (int)(void*)(intPtr + 7);
		}

		public static int LastIndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
		{
			if (valueLength == 0)
			{
				return 0;
			}
			byte value2 = value;
			ref byte second = ref Unsafe.Add(ref value, 1);
			int num = valueLength - 1;
			int num2 = 0;
			while (true)
			{
				int num3 = searchSpaceLength - num2 - num;
				if (num3 <= 0)
				{
					break;
				}
				int num4 = LastIndexOf(ref searchSpace, value2, num3);
				if (num4 == -1)
				{
					break;
				}
				if (SequenceEqual(ref Unsafe.Add(ref searchSpace, num4 + 1), ref second, num))
				{
					return num4;
				}
				num2 += num3 - num4;
			}
			return -1;
		}

		public unsafe static int LastIndexOf(ref byte searchSpace, byte value, int length)
		{
			IntPtr intPtr = (IntPtr)length;
			IntPtr intPtr2 = (IntPtr)length;
			if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
			{
				int num = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
				intPtr2 = (IntPtr)(((length & (Vector<byte>.Count - 1)) + num) & (Vector<byte>.Count - 1));
			}
			while (true)
			{
				if ((nuint)(void*)intPtr2 >= (nuint)8u)
				{
					intPtr2 -= 8;
					intPtr -= 8;
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 7))
					{
						break;
					}
					if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 6))
					{
						if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 5))
						{
							if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 4))
							{
								if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 3))
								{
									if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 2))
									{
										if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr + 1))
										{
											if (value != Unsafe.AddByteOffset(ref searchSpace, intPtr))
											{
												continue;
											}
											goto IL_0254;
										}
										goto IL_025c;
									}
									goto IL_026a;
								}
								goto IL_0278;
							}
							return (int)(void*)(intPtr + 4);
						}
						return (int)(void*)(intPtr + 5);
					}
					return (int)(void*)(intPtr + 6);
				}
				if ((nuint)(void*)intPtr2 >= (nuint)4u)
				{
					intPtr2 -= 4;
					intPtr -= 4;
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 3))
					{
						goto IL_0278;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 2))
					{
						goto IL_026a;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr + 1))
					{
						goto IL_025c;
					}
					if (value == Unsafe.AddByteOffset(ref searchSpace, intPtr))
					{
						goto IL_0254;
					}
				}
				while ((void*)intPtr2 != null)
				{
					intPtr2 -= 1;
					intPtr -= 1;
					if (val

System.Numerics.Vectors.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Globalization;
using System.Numerics.Hashing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using FxResources.System.Numerics.Vectors;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyTitle("System.Numerics.Vectors")]
[assembly: AssemblyDescription("System.Numerics.Vectors")]
[assembly: AssemblyDefaultAlias("System.Numerics.Vectors")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: AssemblyCopyright("© Microsoft Corporation.  All rights reserved.")]
[assembly: AssemblyFileVersion("4.6.26515.06")]
[assembly: AssemblyInformationalVersion("4.6.26515.06 @BuiltBy: dlab-DDVSOWINAGE059 @Branch: release/2.1 @SrcCode: https://github.com/dotnet/corefx/tree/30ab651fcb4354552bd4891619a0bdd81e0ebdbf")]
[assembly: CLSCompliant(true)]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.1.4.0")]
[module: UnverifiableCode]
namespace FxResources.System.Numerics.Vectors
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class MathF
	{
		public const float PI = 3.1415927f;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Abs(float x)
		{
			return Math.Abs(x);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Acos(float x)
		{
			return (float)Math.Acos(x);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Cos(float x)
		{
			return (float)Math.Cos(x);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float IEEERemainder(float x, float y)
		{
			return (float)Math.IEEERemainder(x, y);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Pow(float x, float y)
		{
			return (float)Math.Pow(x, y);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Sin(float x)
		{
			return (float)Math.Sin(x);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Sqrt(float x)
		{
			return (float)Math.Sqrt(x);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float Tan(float x)
		{
			return (float)Math.Tan(x);
		}
	}
	internal static class SR
	{
		private static ResourceManager s_resourceManager;

		private static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(ResourceType));

		internal static Type ResourceType { get; } = typeof(SR);


		internal static string Arg_ArgumentOutOfRangeException => GetResourceString("Arg_ArgumentOutOfRangeException", null);

		internal static string Arg_ElementsInSourceIsGreaterThanDestination => GetResourceString("Arg_ElementsInSourceIsGreaterThanDestination", null);

		internal static string Arg_NullArgumentNullRef => GetResourceString("Arg_NullArgumentNullRef", null);

		internal static string Arg_TypeNotSupported => GetResourceString("Arg_TypeNotSupported", null);

		internal static string Arg_InsufficientNumberOfElements => GetResourceString("Arg_InsufficientNumberOfElements", null);

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool UsingResourceKeys()
		{
			return false;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string text = null;
			try
			{
				text = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			if (defaultString != null && resourceKey.Equals(text, StringComparison.Ordinal))
			{
				return defaultString;
			}
			return text;
		}

		internal static string Format(string resourceFormat, params object[] args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object p1, object p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object p1, object p2, object p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Field, Inherited = false)]
	internal sealed class IntrinsicAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.All)]
	internal class __BlockReflectionAttribute : Attribute
	{
	}
}
namespace System.Numerics
{
	internal class ConstantHelper
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static byte GetByteWithAllBitsSet()
		{
			byte result = 0;
			result = byte.MaxValue;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static sbyte GetSByteWithAllBitsSet()
		{
			sbyte result = 0;
			result = -1;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ushort GetUInt16WithAllBitsSet()
		{
			ushort result = 0;
			result = ushort.MaxValue;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static short GetInt16WithAllBitsSet()
		{
			short result = 0;
			result = -1;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint GetUInt32WithAllBitsSet()
		{
			uint result = 0u;
			result = uint.MaxValue;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int GetInt32WithAllBitsSet()
		{
			int result = 0;
			result = -1;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ulong GetUInt64WithAllBitsSet()
		{
			ulong result = 0uL;
			result = ulong.MaxValue;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static long GetInt64WithAllBitsSet()
		{
			long result = 0L;
			result = -1L;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static float GetSingleWithAllBitsSet()
		{
			float result = 0f;
			*(int*)(&result) = -1;
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static double GetDoubleWithAllBitsSet()
		{
			double result = 0.0;
			*(long*)(&result) = -1L;
			return result;
		}
	}
	[StructLayout(LayoutKind.Explicit)]
	internal struct Register
	{
		[FieldOffset(0)]
		internal byte byte_0;

		[FieldOffset(1)]
		internal byte byte_1;

		[FieldOffset(2)]
		internal byte byte_2;

		[FieldOffset(3)]
		internal byte byte_3;

		[FieldOffset(4)]
		internal byte byte_4;

		[FieldOffset(5)]
		internal byte byte_5;

		[FieldOffset(6)]
		internal byte byte_6;

		[FieldOffset(7)]
		internal byte byte_7;

		[FieldOffset(8)]
		internal byte byte_8;

		[FieldOffset(9)]
		internal byte byte_9;

		[FieldOffset(10)]
		internal byte byte_10;

		[FieldOffset(11)]
		internal byte byte_11;

		[FieldOffset(12)]
		internal byte byte_12;

		[FieldOffset(13)]
		internal byte byte_13;

		[FieldOffset(14)]
		internal byte byte_14;

		[FieldOffset(15)]
		internal byte byte_15;

		[FieldOffset(0)]
		internal sbyte sbyte_0;

		[FieldOffset(1)]
		internal sbyte sbyte_1;

		[FieldOffset(2)]
		internal sbyte sbyte_2;

		[FieldOffset(3)]
		internal sbyte sbyte_3;

		[FieldOffset(4)]
		internal sbyte sbyte_4;

		[FieldOffset(5)]
		internal sbyte sbyte_5;

		[FieldOffset(6)]
		internal sbyte sbyte_6;

		[FieldOffset(7)]
		internal sbyte sbyte_7;

		[FieldOffset(8)]
		internal sbyte sbyte_8;

		[FieldOffset(9)]
		internal sbyte sbyte_9;

		[FieldOffset(10)]
		internal sbyte sbyte_10;

		[FieldOffset(11)]
		internal sbyte sbyte_11;

		[FieldOffset(12)]
		internal sbyte sbyte_12;

		[FieldOffset(13)]
		internal sbyte sbyte_13;

		[FieldOffset(14)]
		internal sbyte sbyte_14;

		[FieldOffset(15)]
		internal sbyte sbyte_15;

		[FieldOffset(0)]
		internal ushort uint16_0;

		[FieldOffset(2)]
		internal ushort uint16_1;

		[FieldOffset(4)]
		internal ushort uint16_2;

		[FieldOffset(6)]
		internal ushort uint16_3;

		[FieldOffset(8)]
		internal ushort uint16_4;

		[FieldOffset(10)]
		internal ushort uint16_5;

		[FieldOffset(12)]
		internal ushort uint16_6;

		[FieldOffset(14)]
		internal ushort uint16_7;

		[FieldOffset(0)]
		internal short int16_0;

		[FieldOffset(2)]
		internal short int16_1;

		[FieldOffset(4)]
		internal short int16_2;

		[FieldOffset(6)]
		internal short int16_3;

		[FieldOffset(8)]
		internal short int16_4;

		[FieldOffset(10)]
		internal short int16_5;

		[FieldOffset(12)]
		internal short int16_6;

		[FieldOffset(14)]
		internal short int16_7;

		[FieldOffset(0)]
		internal uint uint32_0;

		[FieldOffset(4)]
		internal uint uint32_1;

		[FieldOffset(8)]
		internal uint uint32_2;

		[FieldOffset(12)]
		internal uint uint32_3;

		[FieldOffset(0)]
		internal int int32_0;

		[FieldOffset(4)]
		internal int int32_1;

		[FieldOffset(8)]
		internal int int32_2;

		[FieldOffset(12)]
		internal int int32_3;

		[FieldOffset(0)]
		internal ulong uint64_0;

		[FieldOffset(8)]
		internal ulong uint64_1;

		[FieldOffset(0)]
		internal long int64_0;

		[FieldOffset(8)]
		internal long int64_1;

		[FieldOffset(0)]
		internal float single_0;

		[FieldOffset(4)]
		internal float single_1;

		[FieldOffset(8)]
		internal float single_2;

		[FieldOffset(12)]
		internal float single_3;

		[FieldOffset(0)]
		internal double double_0;

		[FieldOffset(8)]
		internal double double_1;
	}
	[System.Runtime.CompilerServices.Intrinsic]
	public struct Vector<T> : IEquatable<Vector<T>>, IFormattable where T : struct
	{
		private struct VectorSizeHelper
		{
			internal Vector<T> _placeholder;

			internal byte _byte;
		}

		private System.Numerics.Register register;

		private static readonly int s_count = InitializeCount();

		private static readonly Vector<T> s_zero = default(Vector<T>);

		private static readonly Vector<T> s_one = new Vector<T>(GetOneValue());

		private static readonly Vector<T> s_allOnes = new Vector<T>(GetAllBitsSetValue());

		public static int Count
		{
			[System.Runtime.CompilerServices.Intrinsic]
			get
			{
				return s_count;
			}
		}

		public static Vector<T> Zero
		{
			[System.Runtime.CompilerServices.Intrinsic]
			get
			{
				return s_zero;
			}
		}

		public static Vector<T> One
		{
			[System.Runtime.CompilerServices.Intrinsic]
			get
			{
				return s_one;
			}
		}

		internal static Vector<T> AllOnes => s_allOnes;

		public unsafe T this[int index]
		{
			[System.Runtime.CompilerServices.Intrinsic]
			get
			{
				if (index >= Count || index < 0)
				{
					throw new IndexOutOfRangeException(System.SR.Format(System.SR.Arg_ArgumentOutOfRangeException, index));
				}
				if (typeof(T) == typeof(byte))
				{
					fixed (byte* ptr = &register.byte_0)
					{
						return (T)(object)ptr[index];
					}
				}
				if (typeof(T) == typeof(sbyte))
				{
					fixed (sbyte* ptr2 = &register.sbyte_0)
					{
						return (T)(object)ptr2[index];
					}
				}
				if (typeof(T) == typeof(ushort))
				{
					fixed (ushort* ptr3 = &register.uint16_0)
					{
						return (T)(object)ptr3[index];
					}
				}
				if (typeof(T) == typeof(short))
				{
					fixed (short* ptr4 = &register.int16_0)
					{
						return (T)(object)ptr4[index];
					}
				}
				if (typeof(T) == typeof(uint))
				{
					fixed (uint* ptr5 = &register.uint32_0)
					{
						return (T)(object)ptr5[index];
					}
				}
				if (typeof(T) == typeof(int))
				{
					fixed (int* ptr6 = &register.int32_0)
					{
						return (T)(object)ptr6[index];
					}
				}
				if (typeof(T) == typeof(ulong))
				{
					fixed (ulong* ptr7 = &register.uint64_0)
					{
						return (T)(object)ptr7[index];
					}
				}
				if (typeof(T) == typeof(long))
				{
					fixed (long* ptr8 = &register.int64_0)
					{
						return (T)(object)ptr8[index];
					}
				}
				if (typeof(T) == typeof(float))
				{
					fixed (float* ptr9 = &register.single_0)
					{
						return (T)(object)ptr9[index];
					}
				}
				if (typeof(T) == typeof(double))
				{
					fixed (double* ptr10 = &register.double_0)
					{
						return (T)(object)ptr10[index];
					}
				}
				throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
			}
		}

		private unsafe static int InitializeCount()
		{
			VectorSizeHelper vectorSizeHelper = default(VectorSizeHelper);
			byte* ptr = &vectorSizeHelper._placeholder.register.byte_0;
			byte* ptr2 = &vectorSizeHelper._byte;
			int num = (int)(ptr2 - ptr);
			int num2 = -1;
			if (typeof(T) == typeof(byte))
			{
				num2 = 1;
			}
			else if (typeof(T) == typeof(sbyte))
			{
				num2 = 1;
			}
			else if (typeof(T) == typeof(ushort))
			{
				num2 = 2;
			}
			else if (typeof(T) == typeof(short))
			{
				num2 = 2;
			}
			else if (typeof(T) == typeof(uint))
			{
				num2 = 4;
			}
			else if (typeof(T) == typeof(int))
			{
				num2 = 4;
			}
			else if (typeof(T) == typeof(ulong))
			{
				num2 = 8;
			}
			else if (typeof(T) == typeof(long))
			{
				num2 = 8;
			}
			else if (typeof(T) == typeof(float))
			{
				num2 = 4;
			}
			else
			{
				if (!(typeof(T) == typeof(double)))
				{
					throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
				}
				num2 = 8;
			}
			return num / num2;
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public unsafe Vector(T value)
		{
			this = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					fixed (byte* ptr = &register.byte_0)
					{
						for (int i = 0; i < Count; i++)
						{
							ptr[i] = (byte)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(sbyte))
				{
					fixed (sbyte* ptr2 = &register.sbyte_0)
					{
						for (int j = 0; j < Count; j++)
						{
							ptr2[j] = (sbyte)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(ushort))
				{
					fixed (ushort* ptr3 = &register.uint16_0)
					{
						for (int k = 0; k < Count; k++)
						{
							ptr3[k] = (ushort)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(short))
				{
					fixed (short* ptr4 = &register.int16_0)
					{
						for (int l = 0; l < Count; l++)
						{
							ptr4[l] = (short)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(uint))
				{
					fixed (uint* ptr5 = &register.uint32_0)
					{
						for (int m = 0; m < Count; m++)
						{
							ptr5[m] = (uint)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(int))
				{
					fixed (int* ptr6 = &register.int32_0)
					{
						for (int n = 0; n < Count; n++)
						{
							ptr6[n] = (int)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(ulong))
				{
					fixed (ulong* ptr7 = &register.uint64_0)
					{
						for (int num = 0; num < Count; num++)
						{
							ptr7[num] = (ulong)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(long))
				{
					fixed (long* ptr8 = &register.int64_0)
					{
						for (int num2 = 0; num2 < Count; num2++)
						{
							ptr8[num2] = (long)(object)value;
						}
					}
				}
				else if (typeof(T) == typeof(float))
				{
					fixed (float* ptr9 = &register.single_0)
					{
						for (int num3 = 0; num3 < Count; num3++)
						{
							ptr9[num3] = (float)(object)value;
						}
					}
				}
				else
				{
					if (!(typeof(T) == typeof(double)))
					{
						return;
					}
					fixed (double* ptr10 = &register.double_0)
					{
						for (int num4 = 0; num4 < Count; num4++)
						{
							ptr10[num4] = (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(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;
			}
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public Vector(T[] values)
			: this(values, 0)
		{
		}

		public unsafe Vector(T[] values, int index)
		{
			this = default(Vector<T>);
			if (values == null)
			{
				throw new NullReferenceException(System.SR.Arg_NullArgumentNullRef);
			}
			if (index < 0 || values.Length - index < Count)
			{
				throw new IndexOutOfRangeException(System.SR.Format(System.SR.Arg_InsufficientNumberOfElements, Count, "values"));
			}
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					fixed (byte* ptr = &register.byte_0)
					{
						for (int i = 0; i < Count; i++)
						{
							ptr[i] = (byte)(object)values[i + index];
						}
					}
				}
				else if (typeof(T) == typeof(sbyte))
				{
					fixed (sbyte* ptr2 = &register.sbyte_0)
					{
						for (int j = 0; j < Count; j++)
						{
							ptr2[j] = (sbyte)(object)values[j + index];
						}
					}
				}
				else if (typeof(T) == typeof(ushort))
				{
					fixed (ushort* ptr3 = &register.uint16_0)
					{
						for (int k = 0; k < Count; k++)
						{
							ptr3[k] = (ushort)(object)values[k + index];
						}
					}
				}
				else if (typeof(T) == typeof(short))
				{
					fixed (short* ptr4 = &register.int16_0)
					{
						for (int l = 0; l < Count; l++)
						{
							ptr4[l] = (short)(object)values[l + index];
						}
					}
				}
				else if (typeof(T) == typeof(uint))
				{
					fixed (uint* ptr5 = &register.uint32_0)
					{
						for (int m = 0; m < Count; m++)
						{
							ptr5[m] = (uint)(object)values[m + index];
						}
					}
				}
				else if (typeof(T) == typeof(int))
				{
					fixed (int* ptr6 = &register.int32_0)
					{
						for (int n = 0; n < Count; n++)
						{
							ptr6[n] = (int)(object)values[n + index];
						}
					}
				}
				else if (typeof(T) == typeof(ulong))
				{
					fixed (ulong* ptr7 = &register.uint64_0)
					{
						for (int num = 0; num < Count; num++)
						{
							ptr7[num] = (ulong)(object)values[num + index];
						}
					}
				}
				else if (typeof(T) == typeof(long))
				{
					fixed (long* ptr8 = &register.int64_0)
					{
						for (int num2 = 0; num2 < Count; num2++)
						{
							ptr8[num2] = (long)(object)values[num2 + index];
						}
					}
				}
				else if (typeof(T) == typeof(float))
				{
					fixed (float* ptr9 = &register.single_0)
					{
						for (int num3 = 0; num3 < Count; num3++)
						{
							ptr9[num3] = (float)(object)values[num3 + index];
						}
					}
				}
				else
				{
					if (!(typeof(T) == typeof(double)))
					{
						return;
					}
					fixed (double* ptr10 = &register.double_0)
					{
						for (int num4 = 0; num4 < Count; num4++)
						{
							ptr10[num4] = (double)(object)values[num4 + index];
						}
					}
				}
			}
			else if (typeof(T) == typeof(byte))
			{
				fixed (byte* ptr11 = &register.byte_0)
				{
					*ptr11 = (byte)(object)values[index];
					ptr11[1] = (byte)(object)values[1 + index];
					ptr11[2] = (byte)(object)values[2 + index];
					ptr11[3] = (byte)(object)values[3 + index];
					ptr11[4] = (byte)(object)values[4 + index];
					ptr11[5] = (byte)(object)values[5 + index];
					ptr11[6] = (byte)(object)values[6 + index];
					ptr11[7] = (byte)(object)values[7 + index];
					ptr11[8] = (byte)(object)values[8 + index];
					ptr11[9] = (byte)(object)values[9 + index];
					ptr11[10] = (byte)(object)values[10 + index];
					ptr11[11] = (byte)(object)values[11 + index];
					ptr11[12] = (byte)(object)values[12 + index];
					ptr11[13] = (byte)(object)values[13 + index];
					ptr11[14] = (byte)(object)values[14 + index];
					ptr11[15] = (byte)(object)values[15 + index];
				}
			}
			else if (typeof(T) == typeof(sbyte))
			{
				fixed (sbyte* ptr12 = &register.sbyte_0)
				{
					*ptr12 = (sbyte)(object)values[index];
					ptr12[1] = (sbyte)(object)values[1 + index];
					ptr12[2] = (sbyte)(object)values[2 + index];
					ptr12[3] = (sbyte)(object)values[3 + index];
					ptr12[4] = (sbyte)(object)values[4 + index];
					ptr12[5] = (sbyte)(object)values[5 + index];
					ptr12[6] = (sbyte)(object)values[6 + index];
					ptr12[7] = (sbyte)(object)values[7 + index];
					ptr12[8] = (sbyte)(object)values[8 + index];
					ptr12[9] = (sbyte)(object)values[9 + index];
					ptr12[10] = (sbyte)(object)values[10 + index];
					ptr12[11] = (sbyte)(object)values[11 + index];
					ptr12[12] = (sbyte)(object)values[12 + index];
					ptr12[13] = (sbyte)(object)values[13 + index];
					ptr12[14] = (sbyte)(object)values[14 + index];
					ptr12[15] = (sbyte)(object)values[15 + index];
				}
			}
			else if (typeof(T) == typeof(ushort))
			{
				fixed (ushort* ptr13 = &register.uint16_0)
				{
					*ptr13 = (ushort)(object)values[index];
					ptr13[1] = (ushort)(object)values[1 + index];
					ptr13[2] = (ushort)(object)values[2 + index];
					ptr13[3] = (ushort)(object)values[3 + index];
					ptr13[4] = (ushort)(object)values[4 + index];
					ptr13[5] = (ushort)(object)values[5 + index];
					ptr13[6] = (ushort)(object)values[6 + index];
					ptr13[7] = (ushort)(object)values[7 + index];
				}
			}
			else if (typeof(T) == typeof(short))
			{
				fixed (short* ptr14 = &register.int16_0)
				{
					*ptr14 = (short)(object)values[index];
					ptr14[1] = (short)(object)values[1 + index];
					ptr14[2] = (short)(object)values[2 + index];
					ptr14[3] = (short)(object)values[3 + index];
					ptr14[4] = (short)(object)values[4 + index];
					ptr14[5] = (short)(object)values[5 + index];
					ptr14[6] = (short)(object)values[6 + index];
					ptr14[7] = (short)(object)values[7 + index];
				}
			}
			else if (typeof(T) == typeof(uint))
			{
				fixed (uint* ptr15 = &register.uint32_0)
				{
					*ptr15 = (uint)(object)values[index];
					ptr15[1] = (uint)(object)values[1 + index];
					ptr15[2] = (uint)(object)values[2 + index];
					ptr15[3] = (uint)(object)values[3 + index];
				}
			}
			else if (typeof(T) == typeof(int))
			{
				fixed (int* ptr16 = &register.int32_0)
				{
					*ptr16 = (int)(object)values[index];
					ptr16[1] = (int)(object)values[1 + index];
					ptr16[2] = (int)(object)values[2 + index];
					ptr16[3] = (int)(object)values[3 + index];
				}
			}
			else if (typeof(T) == typeof(ulong))
			{
				fixed (ulong* ptr17 = &register.uint64_0)
				{
					*ptr17 = (ulong)(object)values[index];
					ptr17[1] = (ulong)(object)values[1 + index];
				}
			}
			else if (typeof(T) == typeof(long))
			{
				fixed (long* ptr18 = &register.int64_0)
				{
					*ptr18 = (long)(object)values[index];
					ptr18[1] = (long)(object)values[1 + index];
				}
			}
			else if (typeof(T) == typeof(float))
			{
				fixed (float* ptr19 = &register.single_0)
				{
					*ptr19 = (float)(object)values[index];
					ptr19[1] = (float)(object)values[1 + index];
					ptr19[2] = (float)(object)values[2 + index];
					ptr19[3] = (float)(object)values[3 + index];
				}
			}
			else if (typeof(T) == typeof(double))
			{
				fixed (double* ptr20 = &register.double_0)
				{
					*ptr20 = (double)(object)values[index];
					ptr20[1] = (double)(object)values[1 + index];
				}
			}
		}

		internal unsafe Vector(void* dataPointer)
			: this(dataPointer, 0)
		{
		}

		internal unsafe Vector(void* dataPointer, int offset)
		{
			this = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				byte* ptr = (byte*)dataPointer;
				ptr += offset;
				fixed (byte* ptr2 = &register.byte_0)
				{
					for (int i = 0; i < Count; i++)
					{
						ptr2[i] = ptr[i];
					}
				}
				return;
			}
			if (typeof(T) == typeof(sbyte))
			{
				sbyte* ptr3 = (sbyte*)dataPointer;
				ptr3 += offset;
				fixed (sbyte* ptr4 = &register.sbyte_0)
				{
					for (int j = 0; j < Count; j++)
					{
						ptr4[j] = ptr3[j];
					}
				}
				return;
			}
			if (typeof(T) == typeof(ushort))
			{
				ushort* ptr5 = (ushort*)dataPointer;
				ptr5 += offset;
				fixed (ushort* ptr6 = &register.uint16_0)
				{
					for (int k = 0; k < Count; k++)
					{
						ptr6[k] = ptr5[k];
					}
				}
				return;
			}
			if (typeof(T) == typeof(short))
			{
				short* ptr7 = (short*)dataPointer;
				ptr7 += offset;
				fixed (short* ptr8 = &register.int16_0)
				{
					for (int l = 0; l < Count; l++)
					{
						ptr8[l] = ptr7[l];
					}
				}
				return;
			}
			if (typeof(T) == typeof(uint))
			{
				uint* ptr9 = (uint*)dataPointer;
				ptr9 += offset;
				fixed (uint* ptr10 = &register.uint32_0)
				{
					for (int m = 0; m < Count; m++)
					{
						ptr10[m] = ptr9[m];
					}
				}
				return;
			}
			if (typeof(T) == typeof(int))
			{
				int* ptr11 = (int*)dataPointer;
				ptr11 += offset;
				fixed (int* ptr12 = &register.int32_0)
				{
					for (int n = 0; n < Count; n++)
					{
						ptr12[n] = ptr11[n];
					}
				}
				return;
			}
			if (typeof(T) == typeof(ulong))
			{
				ulong* ptr13 = (ulong*)dataPointer;
				ptr13 += offset;
				fixed (ulong* ptr14 = &register.uint64_0)
				{
					for (int num = 0; num < Count; num++)
					{
						ptr14[num] = ptr13[num];
					}
				}
				return;
			}
			if (typeof(T) == typeof(long))
			{
				long* ptr15 = (long*)dataPointer;
				ptr15 += offset;
				fixed (long* ptr16 = &register.int64_0)
				{
					for (int num2 = 0; num2 < Count; num2++)
					{
						ptr16[num2] = ptr15[num2];
					}
				}
				return;
			}
			if (typeof(T) == typeof(float))
			{
				float* ptr17 = (float*)dataPointer;
				ptr17 += offset;
				fixed (float* ptr18 = &register.single_0)
				{
					for (int num3 = 0; num3 < Count; num3++)
					{
						ptr18[num3] = ptr17[num3];
					}
				}
				return;
			}
			if (typeof(T) == typeof(double))
			{
				double* ptr19 = (double*)dataPointer;
				ptr19 += offset;
				fixed (double* ptr20 = &register.double_0)
				{
					for (int num4 = 0; num4 < Count; num4++)
					{
						ptr20[num4] = ptr19[num4];
					}
				}
				return;
			}
			throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
		}

		private Vector(ref System.Numerics.Register existingRegister)
		{
			register = existingRegister;
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public void CopyTo(T[] destination)
		{
			CopyTo(destination, 0);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public unsafe void CopyTo(T[] destination, int startIndex)
		{
			if (destination == null)
			{
				throw new NullReferenceException(System.SR.Arg_NullArgumentNullRef);
			}
			if (startIndex < 0 || startIndex >= destination.Length)
			{
				throw new ArgumentOutOfRangeException("startIndex", System.SR.Format(System.SR.Arg_ArgumentOutOfRangeException, startIndex));
			}
			if (destination.Length - startIndex < Count)
			{
				throw new ArgumentException(System.SR.Format(System.SR.Arg_ElementsInSourceIsGreaterThanDestination, startIndex));
			}
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					fixed (byte* ptr = (byte[])(object)destination)
					{
						for (int i = 0; i < Count; i++)
						{
							ptr[startIndex + i] = (byte)(object)this[i];
						}
					}
				}
				else if (typeof(T) == typeof(sbyte))
				{
					fixed (sbyte* ptr2 = (sbyte[])(object)destination)
					{
						for (int j = 0; j < Count; j++)
						{
							ptr2[startIndex + j] = (sbyte)(object)this[j];
						}
					}
				}
				else if (typeof(T) == typeof(ushort))
				{
					fixed (ushort* ptr3 = (ushort[])(object)destination)
					{
						for (int k = 0; k < Count; k++)
						{
							ptr3[startIndex + k] = (ushort)(object)this[k];
						}
					}
				}
				else if (typeof(T) == typeof(short))
				{
					fixed (short* ptr4 = (short[])(object)destination)
					{
						for (int l = 0; l < Count; l++)
						{
							ptr4[startIndex + l] = (short)(object)this[l];
						}
					}
				}
				else if (typeof(T) == typeof(uint))
				{
					fixed (uint* ptr5 = (uint[])(object)destination)
					{
						for (int m = 0; m < Count; m++)
						{
							ptr5[startIndex + m] = (uint)(object)this[m];
						}
					}
				}
				else if (typeof(T) == typeof(int))
				{
					fixed (int* ptr6 = (int[])(object)destination)
					{
						for (int n = 0; n < Count; n++)
						{
							ptr6[startIndex + n] = (int)(object)this[n];
						}
					}
				}
				else if (typeof(T) == typeof(ulong))
				{
					fixed (ulong* ptr7 = (ulong[])(object)destination)
					{
						for (int num = 0; num < Count; num++)
						{
							ptr7[startIndex + num] = (ulong)(object)this[num];
						}
					}
				}
				else if (typeof(T) == typeof(long))
				{
					fixed (long* ptr8 = (long[])(object)destination)
					{
						for (int num2 = 0; num2 < Count; num2++)
						{
							ptr8[startIndex + num2] = (long)(object)this[num2];
						}
					}
				}
				else if (typeof(T) == typeof(float))
				{
					fixed (float* ptr9 = (float[])(object)destination)
					{
						for (int num3 = 0; num3 < Count; num3++)
						{
							ptr9[startIndex + num3] = (float)(object)this[num3];
						}
					}
				}
				else
				{
					if (!(typeof(T) == typeof(double)))
					{
						return;
					}
					fixed (double* ptr10 = (double[])(object)destination)
					{
						for (int num4 = 0; num4 < Count; num4++)
						{
							ptr10[startIndex + num4] = (double)(object)this[num4];
						}
					}
				}
			}
			else if (typeof(T) == typeof(byte))
			{
				fixed (byte* ptr11 = (byte[])(object)destination)
				{
					ptr11[startIndex] = register.byte_0;
					ptr11[startIndex + 1] = register.byte_1;
					ptr11[startIndex + 2] = register.byte_2;
					ptr11[startIndex + 3] = register.byte_3;
					ptr11[startIndex + 4] = register.byte_4;
					ptr11[startIndex + 5] = register.byte_5;
					ptr11[startIndex + 6] = register.byte_6;
					ptr11[startIndex + 7] = register.byte_7;
					ptr11[startIndex + 8] = register.byte_8;
					ptr11[startIndex + 9] = register.byte_9;
					ptr11[startIndex + 10] = register.byte_10;
					ptr11[startIndex + 11] = register.byte_11;
					ptr11[startIndex + 12] = register.byte_12;
					ptr11[startIndex + 13] = register.byte_13;
					ptr11[startIndex + 14] = register.byte_14;
					ptr11[startIndex + 15] = register.byte_15;
				}
			}
			else if (typeof(T) == typeof(sbyte))
			{
				fixed (sbyte* ptr12 = (sbyte[])(object)destination)
				{
					ptr12[startIndex] = register.sbyte_0;
					ptr12[startIndex + 1] = register.sbyte_1;
					ptr12[startIndex + 2] = register.sbyte_2;
					ptr12[startIndex + 3] = register.sbyte_3;
					ptr12[startIndex + 4] = register.sbyte_4;
					ptr12[startIndex + 5] = register.sbyte_5;
					ptr12[startIndex + 6] = register.sbyte_6;
					ptr12[startIndex + 7] = register.sbyte_7;
					ptr12[startIndex + 8] = register.sbyte_8;
					ptr12[startIndex + 9] = register.sbyte_9;
					ptr12[startIndex + 10] = register.sbyte_10;
					ptr12[startIndex + 11] = register.sbyte_11;
					ptr12[startIndex + 12] = register.sbyte_12;
					ptr12[startIndex + 13] = register.sbyte_13;
					ptr12[startIndex + 14] = register.sbyte_14;
					ptr12[startIndex + 15] = register.sbyte_15;
				}
			}
			else if (typeof(T) == typeof(ushort))
			{
				fixed (ushort* ptr13 = (ushort[])(object)destination)
				{
					ptr13[startIndex] = register.uint16_0;
					ptr13[startIndex + 1] = register.uint16_1;
					ptr13[startIndex + 2] = register.uint16_2;
					ptr13[startIndex + 3] = register.uint16_3;
					ptr13[startIndex + 4] = register.uint16_4;
					ptr13[startIndex + 5] = register.uint16_5;
					ptr13[startIndex + 6] = register.uint16_6;
					ptr13[startIndex + 7] = register.uint16_7;
				}
			}
			else if (typeof(T) == typeof(short))
			{
				fixed (short* ptr14 = (short[])(object)destination)
				{
					ptr14[startIndex] = register.int16_0;
					ptr14[startIndex + 1] = register.int16_1;
					ptr14[startIndex + 2] = register.int16_2;
					ptr14[startIndex + 3] = register.int16_3;
					ptr14[startIndex + 4] = register.int16_4;
					ptr14[startIndex + 5] = register.int16_5;
					ptr14[startIndex + 6] = register.int16_6;
					ptr14[startIndex + 7] = register.int16_7;
				}
			}
			else if (typeof(T) == typeof(uint))
			{
				fixed (uint* ptr15 = (uint[])(object)destination)
				{
					ptr15[startIndex] = register.uint32_0;
					ptr15[startIndex + 1] = register.uint32_1;
					ptr15[startIndex + 2] = register.uint32_2;
					ptr15[startIndex + 3] = register.uint32_3;
				}
			}
			else if (typeof(T) == typeof(int))
			{
				fixed (int* ptr16 = (int[])(object)destination)
				{
					ptr16[startIndex] = register.int32_0;
					ptr16[startIndex + 1] = register.int32_1;
					ptr16[startIndex + 2] = register.int32_2;
					ptr16[startIndex + 3] = register.int32_3;
				}
			}
			else if (typeof(T) == typeof(ulong))
			{
				fixed (ulong* ptr17 = (ulong[])(object)destination)
				{
					ptr17[startIndex] = register.uint64_0;
					ptr17[startIndex + 1] = register.uint64_1;
				}
			}
			else if (typeof(T) == typeof(long))
			{
				fixed (long* ptr18 = (long[])(object)destination)
				{
					ptr18[startIndex] = register.int64_0;
					ptr18[startIndex + 1] = register.int64_1;
				}
			}
			else if (typeof(T) == typeof(float))
			{
				fixed (float* ptr19 = (float[])(object)destination)
				{
					ptr19[startIndex] = register.single_0;
					ptr19[startIndex + 1] = register.single_1;
					ptr19[startIndex + 2] = register.single_2;
					ptr19[startIndex + 3] = register.single_3;
				}
			}
			else if (typeof(T) == typeof(double))
			{
				fixed (double* ptr20 = (double[])(object)destination)
				{
					ptr20[startIndex] = register.double_0;
					ptr20[startIndex + 1] = register.double_1;
				}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override bool Equals(object obj)
		{
			if (!(obj is Vector<T>))
			{
				return false;
			}
			return Equals((Vector<T>)obj);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public bool Equals(Vector<T> other)
		{
			if (Vector.IsHardwareAccelerated)
			{
				for (int i = 0; i < Count; i++)
				{
					if (!ScalarEquals(this[i], other[i]))
					{
						return false;
					}
				}
				return true;
			}
			if (typeof(T) == typeof(byte))
			{
				if (register.byte_0 == other.register.byte_0 && register.byte_1 == other.register.byte_1 && register.byte_2 == other.register.byte_2 && register.byte_3 == other.register.byte_3 && register.byte_4 == other.register.byte_4 && register.byte_5 == other.register.byte_5 && register.byte_6 == other.register.byte_6 && register.byte_7 == other.register.byte_7 && register.byte_8 == other.register.byte_8 && register.byte_9 == other.register.byte_9 && register.byte_10 == other.register.byte_10 && register.byte_11 == other.register.byte_11 && register.byte_12 == other.register.byte_12 && register.byte_13 == other.register.byte_13 && register.byte_14 == other.register.byte_14)
				{
					return register.byte_15 == other.register.byte_15;
				}
				return false;
			}
			if (typeof(T) == typeof(sbyte))
			{
				if (register.sbyte_0 == other.register.sbyte_0 && register.sbyte_1 == other.register.sbyte_1 && register.sbyte_2 == other.register.sbyte_2 && register.sbyte_3 == other.register.sbyte_3 && register.sbyte_4 == other.register.sbyte_4 && register.sbyte_5 == other.register.sbyte_5 && register.sbyte_6 == other.register.sbyte_6 && register.sbyte_7 == other.register.sbyte_7 && register.sbyte_8 == other.register.sbyte_8 && register.sbyte_9 == other.register.sbyte_9 && register.sbyte_10 == other.register.sbyte_10 && register.sbyte_11 == other.register.sbyte_11 && register.sbyte_12 == other.register.sbyte_12 && register.sbyte_13 == other.register.sbyte_13 && register.sbyte_14 == other.register.sbyte_14)
				{
					return register.sbyte_15 == other.register.sbyte_15;
				}
				return false;
			}
			if (typeof(T) == typeof(ushort))
			{
				if (register.uint16_0 == other.register.uint16_0 && register.uint16_1 == other.register.uint16_1 && register.uint16_2 == other.register.uint16_2 && register.uint16_3 == other.register.uint16_3 && register.uint16_4 == other.register.uint16_4 && register.uint16_5 == other.register.uint16_5 && register.uint16_6 == other.register.uint16_6)
				{
					return register.uint16_7 == other.register.uint16_7;
				}
				return false;
			}
			if (typeof(T) == typeof(short))
			{
				if (register.int16_0 == other.register.int16_0 && register.int16_1 == other.register.int16_1 && register.int16_2 == other.register.int16_2 && register.int16_3 == other.register.int16_3 && register.int16_4 == other.register.int16_4 && register.int16_5 == other.register.int16_5 && register.int16_6 == other.register.int16_6)
				{
					return register.int16_7 == other.register.int16_7;
				}
				return false;
			}
			if (typeof(T) == typeof(uint))
			{
				if (register.uint32_0 == other.register.uint32_0 && register.uint32_1 == other.register.uint32_1 && register.uint32_2 == other.register.uint32_2)
				{
					return register.uint32_3 == other.register.uint32_3;
				}
				return false;
			}
			if (typeof(T) == typeof(int))
			{
				if (register.int32_0 == other.register.int32_0 && register.int32_1 == other.register.int32_1 && register.int32_2 == other.register.int32_2)
				{
					return register.int32_3 == other.register.int32_3;
				}
				return false;
			}
			if (typeof(T) == typeof(ulong))
			{
				if (register.uint64_0 == other.register.uint64_0)
				{
					return register.uint64_1 == other.register.uint64_1;
				}
				return false;
			}
			if (typeof(T) == typeof(long))
			{
				if (register.int64_0 == other.register.int64_0)
				{
					return register.int64_1 == other.register.int64_1;
				}
				return false;
			}
			if (typeof(T) == typeof(float))
			{
				if (register.single_0 == other.register.single_0 && register.single_1 == other.register.single_1 && register.single_2 == other.register.single_2)
				{
					return register.single_3 == other.register.single_3;
				}
				return false;
			}
			if (typeof(T) == typeof(double))
			{
				if (register.double_0 == other.register.double_0)
				{
					return register.double_1 == other.register.double_1;
				}
				return false;
			}
			throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
		}

		public override int GetHashCode()
		{
			int num = 0;
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					for (int i = 0; i < Count; i++)
					{
						num = HashHelpers.Combine(num, ((byte)(object)this[i]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(sbyte))
				{
					for (int j = 0; j < Count; j++)
					{
						num = HashHelpers.Combine(num, ((sbyte)(object)this[j]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(ushort))
				{
					for (int k = 0; k < Count; k++)
					{
						num = HashHelpers.Combine(num, ((ushort)(object)this[k]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(short))
				{
					for (int l = 0; l < Count; l++)
					{
						num = HashHelpers.Combine(num, ((short)(object)this[l]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(uint))
				{
					for (int m = 0; m < Count; m++)
					{
						num = HashHelpers.Combine(num, ((uint)(object)this[m]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(int))
				{
					for (int n = 0; n < Count; n++)
					{
						num = HashHelpers.Combine(num, ((int)(object)this[n]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(ulong))
				{
					for (int num2 = 0; num2 < Count; num2++)
					{
						num = HashHelpers.Combine(num, ((ulong)(object)this[num2]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(long))
				{
					for (int num3 = 0; num3 < Count; num3++)
					{
						num = HashHelpers.Combine(num, ((long)(object)this[num3]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(float))
				{
					for (int num4 = 0; num4 < Count; num4++)
					{
						num = HashHelpers.Combine(num, ((float)(object)this[num4]).GetHashCode());
					}
					return num;
				}
				if (typeof(T) == typeof(double))
				{
					for (int num5 = 0; num5 < Count; num5++)
					{
						num = HashHelpers.Combine(num, ((double)(object)this[num5]).GetHashCode());
					}
					return num;
				}
				throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
			}
			if (typeof(T) == typeof(byte))
			{
				num = HashHelpers.Combine(num, register.byte_0.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_1.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_2.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_3.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_4.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_5.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_6.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_7.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_8.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_9.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_10.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_11.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_12.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_13.GetHashCode());
				num = HashHelpers.Combine(num, register.byte_14.GetHashCode());
				return HashHelpers.Combine(num, register.byte_15.GetHashCode());
			}
			if (typeof(T) == typeof(sbyte))
			{
				num = HashHelpers.Combine(num, register.sbyte_0.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_1.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_2.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_3.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_4.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_5.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_6.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_7.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_8.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_9.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_10.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_11.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_12.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_13.GetHashCode());
				num = HashHelpers.Combine(num, register.sbyte_14.GetHashCode());
				return HashHelpers.Combine(num, register.sbyte_15.GetHashCode());
			}
			if (typeof(T) == typeof(ushort))
			{
				num = HashHelpers.Combine(num, register.uint16_0.GetHashCode());
				num = HashHelpers.Combine(num, register.uint16_1.GetHashCode());
				num = HashHelpers.Combine(num, register.uint16_2.GetHashCode());
				num = HashHelpers.Combine(num, register.uint16_3.GetHashCode());
				num = HashHelpers.Combine(num, register.uint16_4.GetHashCode());
				num = HashHelpers.Combine(num, register.uint16_5.GetHashCode());
				num = HashHelpers.Combine(num, register.uint16_6.GetHashCode());
				return HashHelpers.Combine(num, register.uint16_7.GetHashCode());
			}
			if (typeof(T) == typeof(short))
			{
				num = HashHelpers.Combine(num, register.int16_0.GetHashCode());
				num = HashHelpers.Combine(num, register.int16_1.GetHashCode());
				num = HashHelpers.Combine(num, register.int16_2.GetHashCode());
				num = HashHelpers.Combine(num, register.int16_3.GetHashCode());
				num = HashHelpers.Combine(num, register.int16_4.GetHashCode());
				num = HashHelpers.Combine(num, register.int16_5.GetHashCode());
				num = HashHelpers.Combine(num, register.int16_6.GetHashCode());
				return HashHelpers.Combine(num, register.int16_7.GetHashCode());
			}
			if (typeof(T) == typeof(uint))
			{
				num = HashHelpers.Combine(num, register.uint32_0.GetHashCode());
				num = HashHelpers.Combine(num, register.uint32_1.GetHashCode());
				num = HashHelpers.Combine(num, register.uint32_2.GetHashCode());
				return HashHelpers.Combine(num, register.uint32_3.GetHashCode());
			}
			if (typeof(T) == typeof(int))
			{
				num = HashHelpers.Combine(num, register.int32_0.GetHashCode());
				num = HashHelpers.Combine(num, register.int32_1.GetHashCode());
				num = HashHelpers.Combine(num, register.int32_2.GetHashCode());
				return HashHelpers.Combine(num, register.int32_3.GetHashCode());
			}
			if (typeof(T) == typeof(ulong))
			{
				num = HashHelpers.Combine(num, register.uint64_0.GetHashCode());
				return HashHelpers.Combine(num, register.uint64_1.GetHashCode());
			}
			if (typeof(T) == typeof(long))
			{
				num = HashHelpers.Combine(num, register.int64_0.GetHashCode());
				return HashHelpers.Combine(num, register.int64_1.GetHashCode());
			}
			if (typeof(T) == typeof(float))
			{
				num = HashHelpers.Combine(num, register.single_0.GetHashCode());
				num = HashHelpers.Combine(num, register.single_1.GetHashCode());
				num = HashHelpers.Combine(num, register.single_2.GetHashCode());
				return HashHelpers.Combine(num, register.single_3.GetHashCode());
			}
			if (typeof(T) == typeof(double))
			{
				num = HashHelpers.Combine(num, register.double_0.GetHashCode());
				return HashHelpers.Combine(num, register.double_1.GetHashCode());
			}
			throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
		}

		public override string ToString()
		{
			return ToString("G", CultureInfo.CurrentCulture);
		}

		public string ToString(string format)
		{
			return ToString(format, CultureInfo.CurrentCulture);
		}

		public string ToString(string format, IFormatProvider formatProvider)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string numberGroupSeparator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator;
			stringBuilder.Append('<');
			for (int i = 0; i < Count - 1; i++)
			{
				stringBuilder.Append(((IFormattable)(object)this[i]).ToString(format, formatProvider));
				stringBuilder.Append(numberGroupSeparator);
				stringBuilder.Append(' ');
			}
			stringBuilder.Append(((IFormattable)(object)this[Count - 1]).ToString(format, formatProvider));
			stringBuilder.Append('>');
			return stringBuilder.ToString();
		}

		public unsafe static Vector<T>operator +(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					byte* ptr = stackalloc byte[(int)(uint)Count];
					for (int i = 0; i < Count; i++)
					{
						ptr[i] = (byte)(object)ScalarAdd(left[i], right[i]);
					}
					return new Vector<T>(ptr);
				}
				if (typeof(T) == typeof(sbyte))
				{
					sbyte* ptr2 = stackalloc sbyte[(int)(uint)Count];
					for (int j = 0; j < Count; j++)
					{
						ptr2[j] = (sbyte)(object)ScalarAdd(left[j], right[j]);
					}
					return new Vector<T>(ptr2);
				}
				if (typeof(T) == typeof(ushort))
				{
					ushort* ptr3 = stackalloc ushort[Count];
					for (int k = 0; k < Count; k++)
					{
						ptr3[k] = (ushort)(object)ScalarAdd(left[k], right[k]);
					}
					return new Vector<T>(ptr3);
				}
				if (typeof(T) == typeof(short))
				{
					short* ptr4 = stackalloc short[Count];
					for (int l = 0; l < Count; l++)
					{
						ptr4[l] = (short)(object)ScalarAdd(left[l], right[l]);
					}
					return new Vector<T>(ptr4);
				}
				if (typeof(T) == typeof(uint))
				{
					uint* ptr5 = stackalloc uint[Count];
					for (int m = 0; m < Count; m++)
					{
						ptr5[m] = (uint)(object)ScalarAdd(left[m], right[m]);
					}
					return new Vector<T>(ptr5);
				}
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[Count];
					for (int n = 0; n < Count; n++)
					{
						ptr6[n] = (int)(object)ScalarAdd(left[n], right[n]);
					}
					return new Vector<T>(ptr6);
				}
				if (typeof(T) == typeof(ulong))
				{
					ulong* ptr7 = stackalloc ulong[Count];
					for (int num = 0; num < Count; num++)
					{
						ptr7[num] = (ulong)(object)ScalarAdd(left[num], right[num]);
					}
					return new Vector<T>(ptr7);
				}
				if (typeof(T) == typeof(long))
				{
					long* ptr8 = stackalloc long[Count];
					for (int num2 = 0; num2 < Count; num2++)
					{
						ptr8[num2] = (long)(object)ScalarAdd(left[num2], right[num2]);
					}
					return new Vector<T>(ptr8);
				}
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[Count];
					for (int num3 = 0; num3 < Count; num3++)
					{
						ptr9[num3] = (float)(object)ScalarAdd(left[num3], right[num3]);
					}
					return new Vector<T>(ptr9);
				}
				if (typeof(T) == typeof(double))
				{
					double* ptr10 = stackalloc double[Count];
					for (int num4 = 0; num4 < Count; num4++)
					{
						ptr10[num4] = (double)(object)ScalarAdd(left[num4], right[num4]);
					}
					return new Vector<T>(ptr10);
				}
				throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
			}
			Vector<T> result = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				result.register.byte_0 = (byte)(left.register.byte_0 + right.register.byte_0);
				result.register.byte_1 = (byte)(left.register.byte_1 + right.register.byte_1);
				result.register.byte_2 = (byte)(left.register.byte_2 + right.register.byte_2);
				result.register.byte_3 = (byte)(left.register.byte_3 + right.register.byte_3);
				result.register.byte_4 = (byte)(left.register.byte_4 + right.register.byte_4);
				result.register.byte_5 = (byte)(left.register.byte_5 + right.register.byte_5);
				result.register.byte_6 = (byte)(left.register.byte_6 + right.register.byte_6);
				result.register.byte_7 = (byte)(left.register.byte_7 + right.register.byte_7);
				result.register.byte_8 = (byte)(left.register.byte_8 + right.register.byte_8);
				result.register.byte_9 = (byte)(left.register.byte_9 + right.register.byte_9);
				result.register.byte_10 = (byte)(left.register.byte_10 + right.register.byte_10);
				result.register.byte_11 = (byte)(left.register.byte_11 + right.register.byte_11);
				result.register.byte_12 = (byte)(left.register.byte_12 + right.register.byte_12);
				result.register.byte_13 = (byte)(left.register.byte_13 + right.register.byte_13);
				result.register.byte_14 = (byte)(left.register.byte_14 + right.register.byte_14);
				result.register.byte_15 = (byte)(left.register.byte_15 + right.register.byte_15);
			}
			else if (typeof(T) == typeof(sbyte))
			{
				result.register.sbyte_0 = (sbyte)(left.register.sbyte_0 + right.register.sbyte_0);
				result.register.sbyte_1 = (sbyte)(left.register.sbyte_1 + right.register.sbyte_1);
				result.register.sbyte_2 = (sbyte)(left.register.sbyte_2 + right.register.sbyte_2);
				result.register.sbyte_3 = (sbyte)(left.register.sbyte_3 + right.register.sbyte_3);
				result.register.sbyte_4 = (sbyte)(left.register.sbyte_4 + right.register.sbyte_4);
				result.register.sbyte_5 = (sbyte)(left.register.sbyte_5 + right.register.sbyte_5);
				result.register.sbyte_6 = (sbyte)(left.register.sbyte_6 + right.register.sbyte_6);
				result.register.sbyte_7 = (sbyte)(left.register.sbyte_7 + right.register.sbyte_7);
				result.register.sbyte_8 = (sbyte)(left.register.sbyte_8 + right.register.sbyte_8);
				result.register.sbyte_9 = (sbyte)(left.register.sbyte_9 + right.register.sbyte_9);
				result.register.sbyte_10 = (sbyte)(left.register.sbyte_10 + right.register.sbyte_10);
				result.register.sbyte_11 = (sbyte)(left.register.sbyte_11 + right.register.sbyte_11);
				result.register.sbyte_12 = (sbyte)(left.register.sbyte_12 + right.register.sbyte_12);
				result.register.sbyte_13 = (sbyte)(left.register.sbyte_13 + right.register.sbyte_13);
				result.register.sbyte_14 = (sbyte)(left.register.sbyte_14 + right.register.sbyte_14);
				result.register.sbyte_15 = (sbyte)(left.register.sbyte_15 + right.register.sbyte_15);
			}
			else if (typeof(T) == typeof(ushort))
			{
				result.register.uint16_0 = (ushort)(left.register.uint16_0 + right.register.uint16_0);
				result.register.uint16_1 = (ushort)(left.register.uint16_1 + right.register.uint16_1);
				result.register.uint16_2 = (ushort)(left.register.uint16_2 + right.register.uint16_2);
				result.register.uint16_3 = (ushort)(left.register.uint16_3 + right.register.uint16_3);
				result.register.uint16_4 = (ushort)(left.register.uint16_4 + right.register.uint16_4);
				result.register.uint16_5 = (ushort)(left.register.uint16_5 + right.register.uint16_5);
				result.register.uint16_6 = (ushort)(left.register.uint16_6 + right.register.uint16_6);
				result.register.uint16_7 = (ushort)(left.register.uint16_7 + right.register.uint16_7);
			}
			else if (typeof(T) == typeof(short))
			{
				result.register.int16_0 = (short)(left.register.int16_0 + right.register.int16_0);
				result.register.int16_1 = (short)(left.register.int16_1 + right.register.int16_1);
				result.register.int16_2 = (short)(left.register.int16_2 + right.register.int16_2);
				result.register.int16_3 = (short)(left.register.int16_3 + right.register.int16_3);
				result.register.int16_4 = (short)(left.register.int16_4 + right.register.int16_4);
				result.register.int16_5 = (short)(left.register.int16_5 + right.register.int16_5);
				result.register.int16_6 = (short)(left.register.int16_6 + right.register.int16_6);
				result.register.int16_7 = (short)(left.register.int16_7 + right.register.int16_7);
			}
			else if (typeof(T) == typeof(uint))
			{
				result.register.uint32_0 = left.register.uint32_0 + right.register.uint32_0;
				result.register.uint32_1 = left.register.uint32_1 + right.register.uint32_1;
				result.register.uint32_2 = left.register.uint32_2 + right.register.uint32_2;
				result.register.uint32_3 = left.register.uint32_3 + right.register.uint32_3;
			}
			else if (typeof(T) == typeof(int))
			{
				result.register.int32_0 = left.register.int32_0 + right.register.int32_0;
				result.register.int32_1 = left.register.int32_1 + right.register.int32_1;
				result.register.int32_2 = left.register.int32_2 + right.register.int32_2;
				result.register.int32_3 = left.register.int32_3 + right.register.int32_3;
			}
			else if (typeof(T) == typeof(ulong))
			{
				result.register.uint64_0 = left.register.uint64_0 + right.register.uint64_0;
				result.register.uint64_1 = left.register.uint64_1 + right.register.uint64_1;
			}
			else if (typeof(T) == typeof(long))
			{
				result.register.int64_0 = left.register.int64_0 + right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 + right.register.int64_1;
			}
			else if (typeof(T) == typeof(float))
			{
				result.register.single_0 = left.register.single_0 + right.register.single_0;
				result.register.single_1 = left.register.single_1 + right.register.single_1;
				result.register.single_2 = left.register.single_2 + right.register.single_2;
				result.register.single_3 = left.register.single_3 + right.register.single_3;
			}
			else if (typeof(T) == typeof(double))
			{
				result.register.double_0 = left.register.double_0 + right.register.double_0;
				result.register.double_1 = left.register.double_1 + right.register.double_1;
			}
			return result;
		}

		public unsafe static Vector<T>operator -(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					byte* ptr = stackalloc byte[(int)(uint)Count];
					for (int i = 0; i < Count; i++)
					{
						ptr[i] = (byte)(object)ScalarSubtract(left[i], right[i]);
					}
					return new Vector<T>(ptr);
				}
				if (typeof(T) == typeof(sbyte))
				{
					sbyte* ptr2 = stackalloc sbyte[(int)(uint)Count];
					for (int j = 0; j < Count; j++)
					{
						ptr2[j] = (sbyte)(object)ScalarSubtract(left[j], right[j]);
					}
					return new Vector<T>(ptr2);
				}
				if (typeof(T) == typeof(ushort))
				{
					ushort* ptr3 = stackalloc ushort[Count];
					for (int k = 0; k < Count; k++)
					{
						ptr3[k] = (ushort)(object)ScalarSubtract(left[k], right[k]);
					}
					return new Vector<T>(ptr3);
				}
				if (typeof(T) == typeof(short))
				{
					short* ptr4 = stackalloc short[Count];
					for (int l = 0; l < Count; l++)
					{
						ptr4[l] = (short)(object)ScalarSubtract(left[l], right[l]);
					}
					return new Vector<T>(ptr4);
				}
				if (typeof(T) == typeof(uint))
				{
					uint* ptr5 = stackalloc uint[Count];
					for (int m = 0; m < Count; m++)
					{
						ptr5[m] = (uint)(object)ScalarSubtract(left[m], right[m]);
					}
					return new Vector<T>(ptr5);
				}
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[Count];
					for (int n = 0; n < Count; n++)
					{
						ptr6[n] = (int)(object)ScalarSubtract(left[n], right[n]);
					}
					return new Vector<T>(ptr6);
				}
				if (typeof(T) == typeof(ulong))
				{
					ulong* ptr7 = stackalloc ulong[Count];
					for (int num = 0; num < Count; num++)
					{
						ptr7[num] = (ulong)(object)ScalarSubtract(left[num], right[num]);
					}
					return new Vector<T>(ptr7);
				}
				if (typeof(T) == typeof(long))
				{
					long* ptr8 = stackalloc long[Count];
					for (int num2 = 0; num2 < Count; num2++)
					{
						ptr8[num2] = (long)(object)ScalarSubtract(left[num2], right[num2]);
					}
					return new Vector<T>(ptr8);
				}
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[Count];
					for (int num3 = 0; num3 < Count; num3++)
					{
						ptr9[num3] = (float)(object)ScalarSubtract(left[num3], right[num3]);
					}
					return new Vector<T>(ptr9);
				}
				if (typeof(T) == typeof(double))
				{
					double* ptr10 = stackalloc double[Count];
					for (int num4 = 0; num4 < Count; num4++)
					{
						ptr10[num4] = (double)(object)ScalarSubtract(left[num4], right[num4]);
					}
					return new Vector<T>(ptr10);
				}
				throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
			}
			Vector<T> result = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				result.register.byte_0 = (byte)(left.register.byte_0 - right.register.byte_0);
				result.register.byte_1 = (byte)(left.register.byte_1 - right.register.byte_1);
				result.register.byte_2 = (byte)(left.register.byte_2 - right.register.byte_2);
				result.register.byte_3 = (byte)(left.register.byte_3 - right.register.byte_3);
				result.register.byte_4 = (byte)(left.register.byte_4 - right.register.byte_4);
				result.register.byte_5 = (byte)(left.register.byte_5 - right.register.byte_5);
				result.register.byte_6 = (byte)(left.register.byte_6 - right.register.byte_6);
				result.register.byte_7 = (byte)(left.register.byte_7 - right.register.byte_7);
				result.register.byte_8 = (byte)(left.register.byte_8 - right.register.byte_8);
				result.register.byte_9 = (byte)(left.register.byte_9 - right.register.byte_9);
				result.register.byte_10 = (byte)(left.register.byte_10 - right.register.byte_10);
				result.register.byte_11 = (byte)(left.register.byte_11 - right.register.byte_11);
				result.register.byte_12 = (byte)(left.register.byte_12 - right.register.byte_12);
				result.register.byte_13 = (byte)(left.register.byte_13 - right.register.byte_13);
				result.register.byte_14 = (byte)(left.register.byte_14 - right.register.byte_14);
				result.register.byte_15 = (byte)(left.register.byte_15 - right.register.byte_15);
			}
			else if (typeof(T) == typeof(sbyte))
			{
				result.register.sbyte_0 = (sbyte)(left.register.sbyte_0 - right.register.sbyte_0);
				result.register.sbyte_1 = (sbyte)(left.register.sbyte_1 - right.register.sbyte_1);
				result.register.sbyte_2 = (sbyte)(left.register.sbyte_2 - right.register.sbyte_2);
				result.register.sbyte_3 = (sbyte)(left.register.sbyte_3 - right.register.sbyte_3);
				result.register.sbyte_4 = (sbyte)(left.register.sbyte_4 - right.register.sbyte_4);
				result.register.sbyte_5 = (sbyte)(left.register.sbyte_5 - right.register.sbyte_5);
				result.register.sbyte_6 = (sbyte)(left.register.sbyte_6 - right.register.sbyte_6);
				result.register.sbyte_7 = (sbyte)(left.register.sbyte_7 - right.register.sbyte_7);
				result.register.sbyte_8 = (sbyte)(left.register.sbyte_8 - right.register.sbyte_8);
				result.register.sbyte_9 = (sbyte)(left.register.sbyte_9 - right.register.sbyte_9);
				result.register.sbyte_10 = (sbyte)(left.register.sbyte_10 - right.register.sbyte_10);
				result.register.sbyte_11 = (sbyte)(left.register.sbyte_11 - right.register.sbyte_11);
				result.register.sbyte_12 = (sbyte)(left.register.sbyte_12 - right.register.sbyte_12);
				result.register.sbyte_13 = (sbyte)(left.register.sbyte_13 - right.register.sbyte_13);
				result.register.sbyte_14 = (sbyte)(left.register.sbyte_14 - right.register.sbyte_14);
				result.register.sbyte_15 = (sbyte)(left.register.sbyte_15 - right.register.sbyte_15);
			}
			else if (typeof(T) == typeof(ushort))
			{
				result.register.uint16_0 = (ushort)(left.register.uint16_0 - right.register.uint16_0);
				result.register.uint16_1 = (ushort)(left.register.uint16_1 - right.register.uint16_1);
				result.register.uint16_2 = (ushort)(left.register.uint16_2 - right.register.uint16_2);
				result.register.uint16_3 = (ushort)(left.register.uint16_3 - right.register.uint16_3);
				result.register.uint16_4 = (ushort)(left.register.uint16_4 - right.register.uint16_4);
				result.register.uint16_5 = (ushort)(left.register.uint16_5 - right.register.uint16_5);
				result.register.uint16_6 = (ushort)(left.register.uint16_6 - right.register.uint16_6);
				result.register.uint16_7 = (ushort)(left.register.uint16_7 - right.register.uint16_7);
			}
			else if (typeof(T) == typeof(short))
			{
				result.register.int16_0 = (short)(left.register.int16_0 - right.register.int16_0);
				result.register.int16_1 = (short)(left.register.int16_1 - right.register.int16_1);
				result.register.int16_2 = (short)(left.register.int16_2 - right.register.int16_2);
				result.register.int16_3 = (short)(left.register.int16_3 - right.register.int16_3);
				result.register.int16_4 = (short)(left.register.int16_4 - right.register.int16_4);
				result.register.int16_5 = (short)(left.register.int16_5 - right.register.int16_5);
				result.register.int16_6 = (short)(left.register.int16_6 - right.register.int16_6);
				result.register.int16_7 = (short)(left.register.int16_7 - right.register.int16_7);
			}
			else if (typeof(T) == typeof(uint))
			{
				result.register.uint32_0 = left.register.uint32_0 - right.register.uint32_0;
				result.register.uint32_1 = left.register.uint32_1 - right.register.uint32_1;
				result.register.uint32_2 = left.register.uint32_2 - right.register.uint32_2;
				result.register.uint32_3 = left.register.uint32_3 - right.register.uint32_3;
			}
			else if (typeof(T) == typeof(int))
			{
				result.register.int32_0 = left.register.int32_0 - right.register.int32_0;
				result.register.int32_1 = left.register.int32_1 - right.register.int32_1;
				result.register.int32_2 = left.register.int32_2 - right.register.int32_2;
				result.register.int32_3 = left.register.int32_3 - right.register.int32_3;
			}
			else if (typeof(T) == typeof(ulong))
			{
				result.register.uint64_0 = left.register.uint64_0 - right.register.uint64_0;
				result.register.uint64_1 = left.register.uint64_1 - right.register.uint64_1;
			}
			else if (typeof(T) == typeof(long))
			{
				result.register.int64_0 = left.register.int64_0 - right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 - right.register.int64_1;
			}
			else if (typeof(T) == typeof(float))
			{
				result.register.single_0 = left.register.single_0 - right.register.single_0;
				result.register.single_1 = left.register.single_1 - right.register.single_1;
				result.register.single_2 = left.register.single_2 - right.register.single_2;
				result.register.single_3 = left.register.single_3 - right.register.single_3;
			}
			else if (typeof(T) == typeof(double))
			{
				result.register.double_0 = left.register.double_0 - right.register.double_0;
				result.register.double_1 = left.register.double_1 - right.register.double_1;
			}
			return result;
		}

		public unsafe static Vector<T>operator *(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					byte* ptr = stackalloc byte[(int)(uint)Count];
					for (int i = 0; i < Count; i++)
					{
						ptr[i] = (byte)(object)ScalarMultiply(left[i], right[i]);
					}
					return new Vector<T>(ptr);
				}
				if (typeof(T) == typeof(sbyte))
				{
					sbyte* ptr2 = stackalloc sbyte[(int)(uint)Count];
					for (int j = 0; j < Count; j++)
					{
						ptr2[j] = (sbyte)(object)ScalarMultiply(left[j], right[j]);
					}
					return new Vector<T>(ptr2);
				}
				if (typeof(T) == typeof(ushort))
				{
					ushort* ptr3 = stackalloc ushort[Count];
					for (int k = 0; k < Count; k++)
					{
						ptr3[k] = (ushort)(object)ScalarMultiply(left[k], right[k]);
					}
					return new Vector<T>(ptr3);
				}
				if (typeof(T) == typeof(short))
				{
					short* ptr4 = stackalloc short[Count];
					for (int l = 0; l < Count; l++)
					{
						ptr4[l] = (short)(object)ScalarMultiply(left[l], right[l]);
					}
					return new Vector<T>(ptr4);
				}
				if (typeof(T) == typeof(uint))
				{
					uint* ptr5 = stackalloc uint[Count];
					for (int m = 0; m < Count; m++)
					{
						ptr5[m] = (uint)(object)ScalarMultiply(left[m], right[m]);
					}
					return new Vector<T>(ptr5);
				}
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[Count];
					for (int n = 0; n < Count; n++)
					{
						ptr6[n] = (int)(object)ScalarMultiply(left[n], right[n]);
					}
					return new Vector<T>(ptr6);
				}
				if (typeof(T) == typeof(ulong))
				{
					ulong* ptr7 = stackalloc ulong[Count];
					for (int num = 0; num < Count; num++)
					{
						ptr7[num] = (ulong)(object)ScalarMultiply(left[num], right[num]);
					}
					return new Vector<T>(ptr7);
				}
				if (typeof(T) == typeof(long))
				{
					long* ptr8 = stackalloc long[Count];
					for (int num2 = 0; num2 < Count; num2++)
					{
						ptr8[num2] = (long)(object)ScalarMultiply(left[num2], right[num2]);
					}
					return new Vector<T>(ptr8);
				}
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[Count];
					for (int num3 = 0; num3 < Count; num3++)
					{
						ptr9[num3] = (float)(object)ScalarMultiply(left[num3], right[num3]);
					}
					return new Vector<T>(ptr9);
				}
				if (typeof(T) == typeof(double))
				{
					double* ptr10 = stackalloc double[Count];
					for (int num4 = 0; num4 < Count; num4++)
					{
						ptr10[num4] = (double)(object)ScalarMultiply(left[num4], right[num4]);
					}
					return new Vector<T>(ptr10);
				}
				throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
			}
			Vector<T> result = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				result.register.byte_0 = (byte)(left.register.byte_0 * right.register.byte_0);
				result.register.byte_1 = (byte)(left.register.byte_1 * right.register.byte_1);
				result.register.byte_2 = (byte)(left.register.byte_2 * right.register.byte_2);
				result.register.byte_3 = (byte)(left.register.byte_3 * right.register.byte_3);
				result.register.byte_4 = (byte)(left.register.byte_4 * right.register.byte_4);
				result.register.byte_5 = (byte)(left.register.byte_5 * right.register.byte_5);
				result.register.byte_6 = (byte)(left.register.byte_6 * right.register.byte_6);
				result.register.byte_7 = (byte)(left.register.byte_7 * right.register.byte_7);
				result.register.byte_8 = (byte)(left.register.byte_8 * right.register.byte_8);
				result.register.byte_9 = (byte)(left.register.byte_9 * right.register.byte_9);
				result.register.byte_10 = (byte)(left.register.byte_10 * right.register.byte_10);
				result.register.byte_11 = (byte)(left.register.byte_11 * right.register.byte_11);
				result.register.byte_12 = (byte)(left.register.byte_12 * right.register.byte_12);
				result.register.byte_13 = (byte)(left.register.byte_13 * right.register.byte_13);
				result.register.byte_14 = (byte)(left.register.byte_14 * right.register.byte_14);
				result.register.byte_15 = (byte)(left.register.byte_15 * right.register.byte_15);
			}
			else if (typeof(T) == typeof(sbyte))
			{
				result.register.sbyte_0 = (sbyte)(left.register.sbyte_0 * right.register.sbyte_0);
				result.register.sbyte_1 = (sbyte)(left.register.sbyte_1 * right.register.sbyte_1);
				result.register.sbyte_2 = (sbyte)(left.register.sbyte_2 * right.register.sbyte_2);
				result.register.sbyte_3 = (sbyte)(left.register.sbyte_3 * right.register.sbyte_3);
				result.register.sbyte_4 = (sbyte)(left.register.sbyte_4 * right.register.sbyte_4);
				result.register.sbyte_5 = (sbyte)(left.register.sbyte_5 * right.register.sbyte_5);
				result.register.sbyte_6 = (sbyte)(left.register.sbyte_6 * right.register.sbyte_6);
				result.register.sbyte_7 = (sbyte)(left.register.sbyte_7 * right.register.sbyte_7);
				result.register.sbyte_8 = (sbyte)(left.register.sbyte_8 * right.register.sbyte_8);
				result.register.sbyte_9 = (sbyte)(left.register.sbyte_9 * right.register.sbyte_9);
				result.register.sbyte_10 = (sbyte)(left.register.sbyte_10 * right.register.sbyte_10);
				result.register.sbyte_11 = (sbyte)(left.register.sbyte_11 * right.register.sbyte_11);
				result.register.sbyte_12 = (sbyte)(left.register.sbyte_12 * right.register.sbyte_12);
				result.register.sbyte_13 = (sbyte)(left.register.sbyte_13 * right.register.sbyte_13);
				result.register.sbyte_14 = (sbyte)(left.register.sbyte_14 * right.register.sbyte_14);
				result.register.sbyte_15 = (sbyte)(left.register.sbyte_15 * right.register.sbyte_15);
			}
			else if (typeof(T) == typeof(ushort))
			{
				result.register.uint16_0 = (ushort)(left.register.uint16_0 * right.register.uint16_0);
				result.register.uint16_1 = (ushort)(left.register.uint16_1 * right.register.uint16_1);
				result.register.uint16_2 = (ushort)(left.register.uint16_2 * right.register.uint16_2);
				result.register.uint16_3 = (ushort)(left.register.uint16_3 * right.register.uint16_3);
				result.register.uint16_4 = (ushort)(left.register.uint16_4 * right.register.uint16_4);
				result.register.uint16_5 = (ushort)(left.register.uint16_5 * right.register.uint16_5);
				result.register.uint16_6 = (ushort)(left.register.uint16_6 * right.register.uint16_6);
				result.register.uint16_7 = (ushort)(left.register.uint16_7 * right.register.uint16_7);
			}
			else if (typeof(T) == typeof(short))
			{
				result.register.int16_0 = (short)(left.register.int16_0 * right.register.int16_0);
				result.register.int16_1 = (short)(left.register.int16_1 * right.register.int16_1);
				result.register.int16_2 = (short)(left.register.int16_2 * right.register.int16_2);
				result.register.int16_3 = (short)(left.register.int16_3 * right.register.int16_3);
				result.register.int16_4 = (short)(left.register.int16_4 * right.register.int16_4);
				result.register.int16_5 = (short)(left.register.int16_5 * right.register.int16_5);
				result.register.int16_6 = (short)(left.register.int16_6 * right.register.int16_6);
				result.register.int16_7 = (short)(left.register.int16_7 * right.register.int16_7);
			}
			else if (typeof(T) == typeof(uint))
			{
				result.register.uint32_0 = left.register.uint32_0 * right.register.uint32_0;
				result.register.uint32_1 = left.register.uint32_1 * right.register.uint32_1;
				result.register.uint32_2 = left.register.uint32_2 * right.register.uint32_2;
				result.register.uint32_3 = left.register.uint32_3 * right.register.uint32_3;
			}
			else if (typeof(T) == typeof(int))
			{
				result.register.int32_0 = left.register.int32_0 * right.register.int32_0;
				result.register.int32_1 = left.register.int32_1 * right.register.int32_1;
				result.register.int32_2 = left.register.int32_2 * right.register.int32_2;
				result.register.int32_3 = left.register.int32_3 * right.register.int32_3;
			}
			else if (typeof(T) == typeof(ulong))
			{
				result.register.uint64_0 = left.register.uint64_0 * right.register.uint64_0;
				result.register.uint64_1 = left.register.uint64_1 * right.register.uint64_1;
			}
			else if (typeof(T) == typeof(long))
			{
				result.register.int64_0 = left.register.int64_0 * right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 * right.register.int64_1;
			}
			else if (typeof(T) == typeof(float))
			{
				result.register.single_0 = left.register.single_0 * right.register.single_0;
				result.register.single_1 = left.register.single_1 * right.register.single_1;
				result.register.single_2 = left.register.single_2 * right.register.single_2;
				result.register.single_3 = left.register.single_3 * right.register.single_3;
			}
			else if (typeof(T) == typeof(double))
			{
				result.register.double_0 = left.register.double_0 * right.register.double_0;
				result.register.double_1 = left.register.double_1 * right.register.double_1;
			}
			return result;
		}

		public static Vector<T>operator *(Vector<T> value, T factor)
		{
			if (Vector.IsHardwareAccelerated)
			{
				return new Vector<T>(factor) * value;
			}
			Vector<T> result = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				result.register.byte_0 = (byte)(value.register.byte_0 * (byte)(object)factor);
				result.register.byte_1 = (byte)(value.register.byte_1 * (byte)(object)factor);
				result.register.byte_2 = (byte)(value.register.byte_2 * (byte)(object)factor);
				result.register.byte_3 = (byte)(value.register.byte_3 * (byte)(object)factor);
				result.register.byte_4 = (byte)(value.register.byte_4 * (byte)(object)factor);
				result.register.byte_5 = (byte)(value.register.byte_5 * (byte)(object)factor);
				result.register.byte_6 = (byte)(value.register.byte_6 * (byte)(object)factor);
				result.register.byte_7 = (byte)(value.register.byte_7 * (byte)(object)factor);
				result.register.byte_8 = (byte)(value.register.byte_8 * (byte)(object)factor);
				result.register.byte_9 = (byte)(value.register.byte_9 * (byte)(object)factor);
				result.register.byte_10 = (byte)(value.register.byte_10 * (byte)(object)factor);
				result.register.byte_11 = (byte)(value.register.byte_11 * (byte)(object)factor);
				result.register.byte_12 = (byte)(value.register.byte_12 * (byte)(object)factor);
				result.register.byte_13 = (byte)(value.register.byte_13 * (byte)(object)factor);
				result.register.byte_14 = (byte)(value.register.byte_14 * (byte)(object)factor);
				result.register.byte_15 = (byte)(value.register.byte_15 * (byte)(object)factor);
			}
			else if (typeof(T) == typeof(sbyte))
			{
				result.register.sbyte_0 = (sbyte)(value.register.sbyte_0 * (sbyte)(object)factor);
				result.register.sbyte_1 = (sbyte)(value.register.sbyte_1 * (sbyte)(object)factor);
				result.register.sbyte_2 = (sbyte)(value.register.sbyte_2 * (sbyte)(object)factor);
				result.register.sbyte_3 = (sbyte)(value.register.sbyte_3 * (sbyte)(object)factor);
				result.register.sbyte_4 = (sbyte)(value.register.sbyte_4 * (sbyte)(object)factor);
				result.register.sbyte_5 = (sbyte)(value.register.sbyte_5 * (sbyte)(object)factor);
				result.register.sbyte_6 = (sbyte)(value.register.sbyte_6 * (sbyte)(object)factor);
				result.register.sbyte_7 = (sbyte)(value.register.sbyte_7 * (sbyte)(object)factor);
				result.register.sbyte_8 = (sbyte)(value.register.sbyte_8 * (sbyte)(object)factor);
				result.register.sbyte_9 = (sbyte)(value.register.sbyte_9 * (sbyte)(object)factor);
				result.register.sbyte_10 = (sbyte)(value.register.sbyte_10 * (sbyte)(object)factor);
				result.register.sbyte_11 = (sbyte)(value.register.sbyte_11 * (sbyte)(object)factor);
				result.register.sbyte_12 = (sbyte)(value.register.sbyte_12 * (sbyte)(object)factor);
				result.register.sbyte_13 = (sbyte)(value.register.sbyte_13 * (sbyte)(object)factor);
				result.register.sbyte_14 = (sbyte)(value.register.sbyte_14 * (sbyte)(object)factor);
				result.register.sbyte_15 = (sbyte)(value.register.sbyte_15 * (sbyte)(object)factor);
			}
			else if (typeof(T) == typeof(ushort))
			{
				result.register.uint16_0 = (ushort)(value.register.uint16_0 * (ushort)(object)factor);
				result.register.uint16_1 = (ushort)(value.register.uint16_1 * (ushort)(object)factor);
				result.register.uint16_2 = (ushort)(value.register.uint16_2 * (ushort)(object)factor);
				result.register.uint16_3 = (ushort)(value.register.uint16_3 * (ushort)(object)factor);
				result.register.uint16_4 = (ushort)(value.register.uint16_4 * (ushort)(object)factor);
				result.register.uint16_5 = (ushort)(value.register.uint16_5 * (ushort)(object)factor);
				result.register.uint16_6 = (ushort)(value.register.uint16_6 * (ushort)(object)factor);
				result.register.uint16_7 = (ushort)(value.register.uint16_7 * (ushort)(object)factor);
			}
			else if (typeof(T) == typeof(short))
			{
				result.register.int16_0 = (short)(value.register.int16_0 * (short)(object)factor);
				result.register.int16_1 = (short)(value.register.int16_1 * (short)(object)factor);
				result.register.int16_2 = (short)(value.register.int16_2 * (short)(object)factor);
				result.register.int16_3 = (short)(value.register.int16_3 * (short)(object)factor);
				result.register.int16_4 = (short)(value.register.int16_4 * (short)(object)factor);
				result.register.int16_5 = (short)(value.register.int16_5 * (short)(object)factor);
				result.register.int16_6 = (short)(value.register.int16_6 * (short)(object)factor);
				result.register.int16_7 = (short)(value.register.int16_7 * (short)(object)factor);
			}
			else if (typeof(T) == typeof(uint))
			{
				result.register.uint32_0 = value.register.uint32_0 * (uint)(object)factor;
				result.register.uint32_1 = value.register.uint32_1 * (uint)(object)factor;
				result.register.uint32_2 = value.register.uint32_2 * (uint)(object)factor;
				result.register.uint32_3 = value.register.uint32_3 * (uint)(object)factor;
			}
			else if (typeof(T) == typeof(int))
			{
				result.register.int32_0 = value.register.int32_0 * (int)(object)factor;
				result.register.int32_1 = value.register.int32_1 * (int)(object)factor;
				result.register.int32_2 = value.register.int32_2 * (int)(object)factor;
				result.register.int32_3 = value.register.int32_3 * (int)(object)factor;
			}
			else if (typeof(T) == typeof(ulong))
			{
				result.register.uint64_0 = value.register.uint64_0 * (ulong)(object)factor;
				result.register.uint64_1 = value.register.uint64_1 * (ulong)(object)factor;
			}
			else if (typeof(T) == typeof(long))
			{
				result.register.int64_0 = value.register.int64_0 * (long)(object)factor;
				result.register.int64_1 = value.register.int64_1 * (long)(object)factor;
			}
			else if (typeof(T) == typeof(float))
			{
				result.register.single_0 = value.register.single_0 * (float)(object)factor;
				result.register.single_1 = value.register.single_1 * (float)(object)factor;
				result.register.single_2 = value.register.single_2 * (float)(object)factor;
				result.register.single_3 = value.register.single_3 * (float)(object)factor;
			}
			else if (typeof(T) == typeof(double))
			{
				result.register.double_0 = value.register.double_0 * (double)(object)factor;
				result.register.double_1 = value.register.double_1 * (double)(object)factor;
			}
			return result;
		}

		public static Vector<T>operator *(T factor, Vector<T> value)
		{
			if (Vector.IsHardwareAccelerated)
			{
				return new Vector<T>(factor) * value;
			}
			Vector<T> result = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				result.register.byte_0 = (byte)(value.register.byte_0 * (byte)(object)factor);
				result.register.byte_1 = (byte)(value.register.byte_1 * (byte)(object)factor);
				result.register.byte_2 = (byte)(value.register.byte_2 * (byte)(object)factor);
				result.register.byte_3 = (byte)(value.register.byte_3 * (byte)(object)factor);
				result.register.byte_4 = (byte)(value.register.byte_4 * (byte)(object)factor);
				result.register.byte_5 = (byte)(value.register.byte_5 * (byte)(object)factor);
				result.register.byte_6 = (byte)(value.register.byte_6 * (byte)(object)factor);
				result.register.byte_7 = (byte)(value.register.byte_7 * (byte)(object)factor);
				result.register.byte_8 = (byte)(value.register.byte_8 * (byte)(object)factor);
				result.register.byte_9 = (byte)(value.register.byte_9 * (byte)(object)factor);
				result.register.byte_10 = (byte)(value.register.byte_10 * (byte)(object)factor);
				result.register.byte_11 = (byte)(value.register.byte_11 * (byte)(object)factor);
				result.register.byte_12 = (byte)(value.register.byte_12 * (byte)(object)factor);
				result.register.byte_13 = (byte)(value.register.byte_13 * (byte)(object)factor);
				result.register.byte_14 = (byte)(value.register.byte_14 * (byte)(object)factor);
				result.register.byte_15 = (byte)(value.register.byte_15 * (byte)(object)factor);
			}
			else if (typeof(T) == typeof(sbyte))
			{
				result.register.sbyte_0 = (sbyte)(value.register.sbyte_0 * (sbyte)(object)factor);
				result.register.sbyte_1 = (sbyte)(value.register.sbyte_1 * (sbyte)(object)factor);
				result.register.sbyte_2 = (sbyte)(value.register.sbyte_2 * (sbyte)(object)factor);
				result.register.sbyte_3 = (sbyte)(value.register.sbyte_3 * (sbyte)(object)factor);
				result.register.sbyte_4 = (sbyte)(value.register.sbyte_4 * (sbyte)(object)factor);
				result.register.sbyte_5 = (sbyte)(value.register.sbyte_5 * (sbyte)(object)factor);
				result.register.sbyte_6 = (sbyte)(value.register.sbyte_6 * (sbyte)(object)factor);
				result.register.sbyte_7 = (sbyte)(value.register.sbyte_7 * (sbyte)(object)factor);
				result.register.sbyte_8 = (sbyte)(value.register.sbyte_8 * (sbyte)(object)factor);
				result.register.sbyte_9 = (sbyte)(value.register.sbyte_9 * (sbyte)(object)factor);
				result.register.sbyte_10 = (sbyte)(value.register.sbyte_10 * (sbyte)(object)factor);
				result.register.sbyte_11 = (sbyte)(value.register.sbyte_11 * (sbyte)(object)factor);
				result.register.sbyte_12 = (sbyte)(value.register.sbyte_12 * (sbyte)(object)factor);
				result.register.sbyte_13 = (sbyte)(value.register.sbyte_13 * (sbyte)(object)factor);
				result.register.sbyte_14 = (sbyte)(value.register.sbyte_14 * (sbyte)(object)factor);
				result.register.sbyte_15 = (sbyte)(value.register.sbyte_15 * (sbyte)(object)factor);
			}
			else if (typeof(T) == typeof(ushort))
			{
				result.register.uint16_0 = (ushort)(value.register.uint16_0 * (ushort)(object)factor);
				result.register.uint16_1 = (ushort)(value.register.uint16_1 * (ushort)(object)factor);
				result.register.uint16_2 = (ushort)(value.register.uint16_2 * (ushort)(object)factor);
				result.register.uint16_3 = (ushort)(value.register.uint16_3 * (ushort)(object)factor);
				result.register.uint16_4 = (ushort)(value.register.uint16_4 * (ushort)(object)factor);
				result.register.uint16_5 = (ushort)(value.register.uint16_5 * (ushort)(object)factor);
				result.register.uint16_6 = (ushort)(value.register.uint16_6 * (ushort)(object)factor);
				result.register.uint16_7 = (ushort)(value.register.uint16_7 * (ushort)(object)factor);
			}
			else if (typeof(T) == typeof(short))
			{
				result.register.int16_0 = (short)(value.register.int16_0 * (short)(object)factor);
				result.register.int16_1 = (short)(value.register.int16_1 * (short)(object)factor);
				result.register.int16_2 = (short)(value.register.int16_2 * (short)(object)factor);
				result.register.int16_3 = (short)(value.register.int16_3 * (short)(object)factor);
				result.register.int16_4 = (short)(value.register.int16_4 * (short)(object)factor);
				result.register.int16_5 = (short)(value.register.int16_5 * (short)(object)factor);
				result.register.int16_6 = (short)(value.register.int16_6 * (short)(object)factor);
				result.register.int16_7 = (short)(value.register.int16_7 * (short)(object)factor);
			}
			else if (typeof(T) == typeof(uint))
			{
				result.register.uint32_0 = value.register.uint32_0 * (uint)(object)factor;
				result.register.uint32_1 = value.register.uint32_1 * (uint)(object)factor;
				result.register.uint32_2 = value.register.uint32_2 * (uint)(object)factor;
				result.register.uint32_3 = value.register.uint32_3 * (uint)(object)factor;
			}
			else if (typeof(T) == typeof(int))
			{
				result.register.int32_0 = value.register.int32_0 * (int)(object)factor;
				result.register.int32_1 = value.register.int32_1 * (int)(object)factor;
				result.register.int32_2 = value.register.int32_2 * (int)(object)factor;
				result.register.int32_3 = value.register.int32_3 * (int)(object)factor;
			}
			else if (typeof(T) == typeof(ulong))
			{
				result.register.uint64_0 = value.register.uint64_0 * (ulong)(object)factor;
				result.register.uint64_1 = value.register.uint64_1 * (ulong)(object)factor;
			}
			else if (typeof(T) == typeof(long))
			{
				result.register.int64_0 = value.register.int64_0 * (long)(object)factor;
				result.register.int64_1 = value.register.int64_1 * (long)(object)factor;
			}
			else if (typeof(T) == typeof(float))
			{
				result.register.single_0 = value.register.single_0 * (float)(object)factor;
				result.register.single_1 = value.register.single_1 * (float)(object)factor;
				result.register.single_2 = value.register.single_2 * (float)(object)factor;
				result.register.single_3 = value.register.single_3 * (float)(object)factor;
			}
			else if (typeof(T) == typeof(double))
			{
				result.register.double_0 = value.register.double_0 * (double)(object)factor;
				result.register.double_1 = value.register.double_1 * (double)(object)factor;
			}
			return result;
		}

		public unsafe static Vector<T>operator /(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					byte* ptr = stackalloc byte[(int)(uint)Count];
					for (int i = 0; i < Count; i++)
					{
						ptr[i] = (byte)(object)ScalarDivide(left[i], right[i]);
					}
					return new Vector<T>(ptr);
				}
				if (typeof(T) == typeof(sbyte))
				{
					sbyte* ptr2 = stackalloc sbyte[(int)(uint)Count];
					for (int j = 0; j < Count; j++)
					{
						ptr2[j] = (sbyte)(object)ScalarDivide(left[j], right[j]);
					}
					return new Vector<T>(ptr2);
				}
				if (typeof(T) == typeof(ushort))
				{
					ushort* ptr3 = stackalloc ushort[Count];
					for (int k = 0; k < Count; k++)
					{
						ptr3[k] = (ushort)(object)ScalarDivide(left[k], right[k]);
					}
					return new Vector<T>(ptr3);
				}
				if (typeof(T) == typeof(short))
				{
					short* ptr4 = stackalloc short[Count];
					for (int l = 0; l < Count; l++)
					{
						ptr4[l] = (short)(object)ScalarDivide(left[l], right[l]);
					}
					return new Vector<T>(ptr4);
				}
				if (typeof(T) == typeof(uint))
				{
					uint* ptr5 = stackalloc uint[Count];
					for (int m = 0; m < Count; m++)
					{
						ptr5[m] = (uint)(object)ScalarDivide(left[m], right[m]);
					}
					return new Vector<T>(ptr5);
				}
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[Count];
					for (int n = 0; n < Count; n++)
					{
						ptr6[n] = (int)(object)ScalarDivide(left[n], right[n]);
					}
					return new Vector<T>(ptr6);
				}
				if (typeof(T) == typeof(ulong))
				{
					ulong* ptr7 = stackalloc ulong[Count];
					for (int num = 0; num < Count; num++)
					{
						ptr7[num] = (ulong)(object)ScalarDivide(left[num], right[num]);
					}
					return new Vector<T>(ptr7);
				}
				if (typeof(T) == typeof(long))
				{
					long* ptr8 = stackalloc long[Count];
					for (int num2 = 0; num2 < Count; num2++)
					{
						ptr8[num2] = (long)(object)ScalarDivide(left[num2], right[num2]);
					}
					return new Vector<T>(ptr8);
				}
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[Count];
					for (int num3 = 0; num3 < Count; num3++)
					{
						ptr9[num3] = (float)(object)ScalarDivide(left[num3], right[num3]);
					}
					return new Vector<T>(ptr9);
				}
				if (typeof(T) == typeof(double))
				{
					double* ptr10 = stackalloc double[Count];
					for (int num4 = 0; num4 < Count; num4++)
					{
						ptr10[num4] = (double)(object)ScalarDivide(left[num4], right[num4]);
					}
					return new Vector<T>(ptr10);
				}
				throw new NotSupportedException(System.SR.Arg_TypeNotSupported);
			}
			Vector<T> result = default(Vector<T>);
			if (typeof(T) == typeof(byte))
			{
				result.register.byte_0 = (byte)(left.register.byte_0 / right.register.byte_0);
				result.register.byte_1 = (byte)(left.register.byte_1 / right.register.byte_1);
				result.register.byte_2 = (byte)(left.register.byte_2 / right.register.byte_2);
				result.register.byte_3 = (byte)(left.register.byte_3 / right.register.byte_3);
				result.register.byte_4 = (byte)(left.register.byte_4 / right.register.byte_4);
				result.register.byte_5 = (byte)(left.register.byte_5 / right.register.byte_5);
				result.register.byte_6 = (byte)(left.register.byte_6 / right.register.byte_6);
				result.register.byte_7 = (byte)(left.register.byte_7 / right.register.byte_7);
				result.register.byte_8 = (byte)(left.register.byte_8 / right.register.byte_8);
				result.register.byte_9 = (byte)(left.register.byte_9 / right.register.byte_9);
				result.register.byte_10 = (byte)(left.register.byte_10 / right.register.byte_10);
				result.register.byte_11 = (byte)(left.register.byte_11 / right.register.byte_11);
				result.register.byte_12 = (byte)(left.register.byte_12 / right.register.byte_12);
				result.register.byte_13 = (byte)(left.register.byte_13 / right.register.byte_13);
				result.register.byte_14 = (byte)(left.register.byte_14 / right.register.byte_14);
				result.register.byte_15 = (byte)(left.register.byte_15 / right.register.byte_15);
			}
			else if (typeof(T) == typeof(sbyte))
			{
				result.register.sbyte_0 = (sbyte)(left.register.sbyte_0 / right.register.sbyte_0);
				result.register.sbyte_1 = (sbyte)(left.register.sbyte_1 / right.register.sbyte_1);
				result.register.sbyte_2 = (sbyte)(left.register.sbyte_2 / right.register.sbyte_2);
				result.register.sbyte_3 = (sbyte)(left.register.sbyte_3 / right.register.sbyte_3);
				result.register.sbyte_4 = (sbyte)(left.register.sbyte_4 / right.register.sbyte_4);
				result.register.sbyte_5 = (sbyte)(left.register.sbyte_5 / right.register.sbyte_5);
				result.register.sbyte_6 = (sbyte)(left.register.sbyte_6 / right.register.sbyte_6);
				result.register.sbyte_7 = (sbyte)(left.register.sbyte_7 / right.register.sbyte_7);
				result.register.sbyte_8 = (sbyte)(left.register.sbyte_8 / right.register.sbyte_8);
				result.register.sbyte_9 = (sbyte)(left.register.sbyte_9 / right.register.sbyte_9);
				result.register.sbyte_10 = (sbyte)(left.register.sbyte_10 / right.register.sbyte_10);
				result.register.sbyte_11 = (sbyte)(left.register.sbyte_11 / right.register.sbyte_11);
				result.register.sbyte_12 = (sbyte)(left.register.sbyte_12 / right.register.sbyte_12);
				result.register.sbyte_13 = (sbyte)(left.register.sbyte_13 / right.register.sbyte_13);
				result.register.sbyte_14 = (sbyte)(left.register.sbyte_14 / right.register.sbyte_14);
				result.register.sbyte_15 = (sbyte)(left.register.sbyte_15 / right.register.sbyte_15);
			}
			else if (typeof(T) == typeof(ushort))
			{
				result.register.uint16_0 = (ushort)(left.register.uint16_0 / right.register.uint16_0);
				result.register.uint16_1 = (ushort)(left.register.uint16_1 / right.register.uint16_1);
				result.register.uint16_2 = (ushort)(left.register.uint16_2 / right.register.uint16_2);
				result.register.uint16_3 = (ushort)(left.register.uint16_3 / right.register.uint16_3);
				result.register.uint16_4 = (ushort)(left.register.uint16_4 / right.register.uint16_4);
				result.register.uint16_5 = (ushort)(left.register.uint16_5 / right.register.uint16_5);
				result.register.uint16_6 = (ushort)(left.register.uint16_6 / right.register.uint16_6);
				result.register.uint16_7 = (ushort)(left.register.uint16_7 / right.register.uint16_7);
			}
			else if (typeof(T) == typeof(short))
			{
				result.register.int16_0 = (short)(left.register.int16_0 / right.register.int16_0);
				result.register.int16_1 = (short)(left.register.int16_1 / right.register.int16_1);
				result.register.int16_2 = (short)(left.register.int16_2 / right.register.int16_2);
				result.register.int16_3 = (short)(left.register.int16_3 / right.register.int16_3);
				result.register.int16_4 = (short)(left.register.int16_4 / right.register.int16_4);
				result.register.int16_5 = (short)(left.register.int16_5 / right.register.int16_5);
				result.register.int16_6 = (short)(left.register.int16_6 / right.register.int16_6);
				result.register.int16_7 = (short)(left.register.int16_7 / right.register.int16_7);
			}
			else if (typeof(T) == typeof(uint))
			{
				result.register.uint32_0 = left.register.uint32_0 / right.register.uint32_0;
				result.register.uint32_1 = left.register.uint32_1 / right.register.uint32_1;
				result.register.uint32_2 = left.register.uint32_2 / right.register.uint32_2;
				result.register.uint32_3 = left.register.uint32_3 / right.register.uint32_3;
			}
			else if (typeof(T) == typeof(int))
			{
				result.register.int32_0 = left.register.int32_0 / right.register.int32_0;
				result.register.int32_1 = left.register.int32_1 / right.register.int32_1;
				result.register.int32_2 = left.register.int32_2 / right.register.int32_2;
				result.register.int32_3 = left.register.int32_3 / right.register.int32_3;
			}
			else if (typeof(T) == typeof(ulong))
			{
				result.register.uint64_0 = left.register.uint64_0 / right.register.uint64_0;
				result.register.uint64_1 = left.register.uint64_1 / right.register.uint64_1;
			}
			else if (typeof(T) == typeof(long))
			{
				result.register.int64_0 = left.register.int64_0 / right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 / right.register.int64_1;
			}
			else if (typeof(T) == typeof(float))
			{
				result.register.single_0 = left.register.single_0 / right.register.single_0;
				result.register.single_1 = left.register.single_1 / right.register.single_1;
				result.register.single_2 = left.register.single_2 / right.register.single_2;
				result.register.single_3 = left.register.single_3 / right.register.single_3;
			}
			else if (typeof(T) == typeof(double))
			{
				result.register.double_0 = left.register.double_0 / right.register.double_0;
				result.register.double_1 = left.register.double_1 / right.register.double_1;
			}
			return result;
		}

		public static Vector<T>operator -(Vector<T> value)
		{
			return Zero - value;
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public unsafe static Vector<T>operator &(Vector<T> left, Vector<T> right)
		{
			Vector<T> result = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				long* ptr = &result.register.int64_0;
				long* ptr2 = &left.register.int64_0;
				long* ptr3 = &right.register.int64_0;
				for (int i = 0; i < Vector<long>.Count; i++)
				{
					ptr[i] = ptr2[i] & ptr3[i];
				}
			}
			else
			{
				result.register.int64_0 = left.register.int64_0 & right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 & right.register.int64_1;
			}
			return result;
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public unsafe static Vector<T>operator |(Vector<T> left, Vector<T> right)
		{
			Vector<T> result = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				long* ptr = &result.register.int64_0;
				long* ptr2 = &left.register.int64_0;
				long* ptr3 = &right.register.int64_0;
				for (int i = 0; i < Vector<long>.Count; i++)
				{
					ptr[i] = ptr2[i] | ptr3[i];
				}
			}
			else
			{
				result.register.int64_0 = left.register.int64_0 | right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 | right.register.int64_1;
			}
			return result;
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public unsafe static Vector<T>operator ^(Vector<T> left, Vector<T> right)
		{
			Vector<T> result = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				long* ptr = &result.register.int64_0;
				long* ptr2 = &left.register.int64_0;
				long* ptr3 = &right.register.int64_0;
				for (int i = 0; i < Vector<long>.Count; i++)
				{
					ptr[i] = ptr2[i] ^ ptr3[i];
				}
			}
			else
			{
				result.register.int64_0 = left.register.int64_0 ^ right.register.int64_0;
				result.register.int64_1 = left.register.int64_1 ^ right.register.int64_1;
			}
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Vector<T>operator ~(Vector<T> value)
		{
			return s_allOnes ^ value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool operator ==(Vector<T> left, Vector<T> right)
		{
			return left.Equals(right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool operator !=(Vector<T> left, Vector<T> right)
		{
			return !(left == right);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<byte>(Vector<T> value)
		{
			return new Vector<byte>(ref value.register);
		}

		[CLSCompliant(false)]
		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<sbyte>(Vector<T> value)
		{
			return new Vector<sbyte>(ref value.register);
		}

		[CLSCompliant(false)]
		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<ushort>(Vector<T> value)
		{
			return new Vector<ushort>(ref value.register);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<short>(Vector<T> value)
		{
			return new Vector<short>(ref value.register);
		}

		[CLSCompliant(false)]
		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<uint>(Vector<T> value)
		{
			return new Vector<uint>(ref value.register);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<int>(Vector<T> value)
		{
			return new Vector<int>(ref value.register);
		}

		[CLSCompliant(false)]
		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<ulong>(Vector<T> value)
		{
			return new Vector<ulong>(ref value.register);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<long>(Vector<T> value)
		{
			return new Vector<long>(ref value.register);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<float>(Vector<T> value)
		{
			return new Vector<float>(ref value.register);
		}

		[System.Runtime.CompilerServices.Intrinsic]
		public static explicit operator Vector<double>(Vector<T> value)
		{
			return new Vector<double>(ref value.register);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.CompilerServices.Intrinsic]
		internal unsafe static Vector<T> Equals(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(byte))
				{
					byte* ptr = stackalloc byte[(int)(uint)Count];
					fo

System.Runtime.CompilerServices.Unsafe.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: AssemblyProduct("Microsoft® .NET Framework")]
[assembly: CLSCompliant(false)]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyDescription("System.Runtime.CompilerServices.Unsafe")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0")]
[assembly: AssemblyTitle("System.Runtime.CompilerServices.Unsafe")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCopyright("© Microsoft Corporation.  All rights reserved.")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyVersion("6.0.0.0")]
namespace System.Runtime.CompilerServices
{
	public static class Unsafe
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static T Read<T>(void* source)
		{
			return Unsafe.Read<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static T ReadUnaligned<T>(void* source)
		{
			return Unsafe.ReadUnaligned<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static T ReadUnaligned<T>(ref byte source)
		{
			return Unsafe.ReadUnaligned<T>(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void Write<T>(void* destination, T value)
		{
			Unsafe.Write(destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void WriteUnaligned<T>(void* destination, T value)
		{
			Unsafe.WriteUnaligned(destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void WriteUnaligned<T>(ref byte destination, T value)
		{
			Unsafe.WriteUnaligned(ref destination, value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void Copy<T>(void* destination, ref T source)
		{
			Unsafe.Write(destination, source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void Copy<T>(ref T destination, void* source)
		{
			destination = Unsafe.Read<T>(source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void* AsPointer<T>(ref T value)
		{
			return Unsafe.AsPointer(ref value);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void SkipInit<T>(out T value)
		{
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static int SizeOf<T>()
		{
			return Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void CopyBlock(void* destination, void* source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlock(destination, source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void CopyBlock(ref byte destination, ref byte source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlock(ref destination, ref source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void CopyBlockUnaligned(void* destination, void* source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlockUnaligned(destination, source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void CopyBlockUnaligned(ref byte destination, ref byte source, uint byteCount)
		{
			// IL cpblk instruction
			Unsafe.CopyBlockUnaligned(ref destination, ref source, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void InitBlock(void* startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlock(startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void InitBlock(ref byte startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlock(ref startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlockUnaligned(startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount)
		{
			// IL initblk instruction
			Unsafe.InitBlockUnaligned(ref startAddress, value, byteCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static T As<T>(object o) where T : class
		{
			return (T)o;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static ref T AsRef<T>(void* source)
		{
			return ref *(T*)source;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T AsRef<T>(in T source)
		{
			return ref source;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref TTo As<TFrom, TTo>(ref TFrom source)
		{
			return ref Unsafe.As<TFrom, TTo>(ref source);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Unbox<T>(object box) where T : struct
		{
			return ref (T)box;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Add<T>(ref T source, int elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void* Add<T>(void* source, int elementOffset)
		{
			return (byte*)source + (nint)elementOffset * (nint)Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Add<T>(ref T source, IntPtr elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ref T Add<T>(ref T source, [System.Runtime.Versioning.NonVersionable] nuint elementOffset)
		{
			return ref Unsafe.Add(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T AddByteOffset<T>(ref T source, IntPtr byteOffset)
		{
			return ref Unsafe.AddByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ref T AddByteOffset<T>(ref T source, [System.Runtime.Versioning.NonVersionable] nuint byteOffset)
		{
			return ref Unsafe.AddByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Subtract<T>(ref T source, int elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static void* Subtract<T>(void* source, int elementOffset)
		{
			return (byte*)source - (nint)elementOffset * (nint)Unsafe.SizeOf<T>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T Subtract<T>(ref T source, IntPtr elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ref T Subtract<T>(ref T source, [System.Runtime.Versioning.NonVersionable] nuint elementOffset)
		{
			return ref Unsafe.Subtract(ref source, elementOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static ref T SubtractByteOffset<T>(ref T source, IntPtr byteOffset)
		{
			return ref Unsafe.SubtractByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static ref T SubtractByteOffset<T>(ref T source, [System.Runtime.Versioning.NonVersionable] nuint byteOffset)
		{
			return ref Unsafe.SubtractByteOffset(ref source, byteOffset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static IntPtr ByteOffset<T>(ref T origin, ref T target)
		{
			return Unsafe.ByteOffset(target: ref target, origin: ref origin);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static bool AreSame<T>(ref T left, ref T right)
		{
			return Unsafe.AreSame(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static bool IsAddressGreaterThan<T>(ref T left, ref T right)
		{
			return Unsafe.IsAddressGreaterThan(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public static bool IsAddressLessThan<T>(ref T left, ref T right)
		{
			return Unsafe.IsAddressLessThan(ref left, ref right);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static bool IsNullRef<T>(ref T source)
		{
			return Unsafe.AsPointer(ref source) == null;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[System.Runtime.Versioning.NonVersionable]
		public unsafe static ref T NullRef<T>()
		{
			return ref *(T*)null;
		}
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	internal sealed class NonVersionableAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[Microsoft.CodeAnalysis.Embedded]
	[CompilerGenerated]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] A_0)
		{
			TransformFlags = A_0;
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}