public async Task Encode(ReadOnlyMemory<byte>[] sources, int[] index, Memory<byte>[] repairs, int packetLength, int concurrency = 1, CancellationToken token = default) { if (sources == null) throw new ArgumentNullException(nameof(sources)); if (repairs == null) throw new ArgumentNullException(nameof(repairs)); if (index == null) throw new ArgumentNullException(nameof(index)); await Enumerable.Range(0, repairs.Length).ForEachAsync(row => { return Task.Run(() => { token.ThrowIfCancellationRequested(); // *remember* indices start at 0, k starts at 1. if (index[row] < _k) { // < k, systematic so direct copy. BytesOperations.Copy(sources[index[row]].Span, repairs[row].Span, packetLength); } else { // index[row] >= k && index[row] < n int pos = index[row] * _k; BytesOperations.Zero(repairs[row].Span.Slice(packetLength)); for (int col = 0; col < _k; col++) { token.ThrowIfCancellationRequested(); ReadSolomonMath.AddMul(sources[col].Span, repairs[row].Span, _encMatrix[pos + col], packetLength); } } }); }, concurrency, token, false); }
public async Task Decode(Memory<byte>[] packets, int[] index, int packetLength, int concurrency = 1, CancellationToken token = default) { if (packets == null) throw new ArgumentNullException(nameof(packets)); if (index == null) throw new ArgumentNullException(nameof(index)); Shuffle(packets, index, _k); var decMatrix = ReadSolomonMath.CreateDecodeMatrix(_encMatrix, index, _k, _n); // do the actual decoding.. var tempPackets = new byte[_k][]; await Enumerable.Range(0, _k).ForEachAsync(row => { return Task.Run(() => { token.ThrowIfCancellationRequested(); if (index[row] >= _k) { tempPackets[row] = _bufferPool.GetArrayPool().Rent(packetLength); BytesOperations.Zero(tempPackets[row].AsSpan(0, packetLength)); for (int col = 0; col < _k; col++) { token.ThrowIfCancellationRequested(); ReadSolomonMath.AddMul(packets[col].Span, tempPackets[row], decMatrix[row * _k + col], packetLength); } } }); }, concurrency, token, false); token.ThrowIfCancellationRequested(); // move pkts to their final destination for (int row = 0; row < _k; row++) { if (index[row] >= _k) { // only copy those actually decoded. BytesOperations.Copy(tempPackets[row], packets[row].Span, packetLength); index[row] = row; _bufferPool.GetArrayPool().Return(tempPackets[row]); } } }