private string FormatEntry(double frequency, NetworkParametersMatrix matrix)
        {
            string formatString = settings.NumericFormatString;

            if (string.IsNullOrEmpty(settings.NumericFormatString))
            {
                formatString = "0.00000000000E+00";
            }
            IFormatProvider provider = settings.NumericFormatProvider ?? CultureInfo.CurrentCulture.NumberFormat;

            string width = string.Empty, frequencyWidth = string.Empty;
            string columnPad = string.Empty;

            if (settings.UnifiedColumnWidth)
            {
                width          = "," + settings.ColumnWidth;
                frequencyWidth = "," + (-settings.ColumnWidth);
                columnPad      = string.Empty.PadRight(settings.ColumnWidth);
            }
            string compositeFormatString    = $"{{0{width}:{formatString}}}";
            string frequencyCompositeString = $"{{0{frequencyWidth}:{formatString}}}";

            int        numPorts = matrix.NumPorts;
            ListFormat format   = core.GetListFormat(numPorts);

            List <double> parameters = new List <double>();

            // Prepare frequency
            double scaledFrequency = frequency / Options.FrequencyUnit.GetMultiplier();

            foreach (var(_, parameter) in matrix.EnumerateParameters(format))
            {
                switch (Options.Format)
                {
                case FormatType.DecibelAngle:
                    parameters.Add(parameter.Magnitude_dB);
                    parameters.Add(parameter.Phase_deg);
                    break;

                case FormatType.MagnitudeAngle:
                    parameters.Add(parameter.Magnitude);
                    parameters.Add(parameter.Phase_deg);
                    break;

                case FormatType.RealImaginary:
                    parameters.Add(parameter.Real);
                    parameters.Add(parameter.Imaginary);
                    break;
                }
            }

            string frequencyString  = string.Format(settings.NumericFormatProvider, frequencyCompositeString, scaledFrequency);
            var    parametersString = parameters.Select(p => string.Format(settings.NumericFormatProvider, compositeFormatString, p));

            string formattedEntry = FormatMatrix(frequencyString, columnPad, parametersString, numPorts);

            return(formattedEntry);
        }
        /// <summary>Writes the frequency and <see cref="NetworkParametersMatrix"/> the network data of the file.</summary>
        /// <param name="frequency">The frequency of the network data to be written.</param>
        /// /// <param name="matrix">The network data to be written.</param>
        /// <remarks>If <see cref="WriteHeader"/> has not yet been called, this method will be called automatically before writing any network data.</remarks>
        public void WriteData(double frequency, NetworkParametersMatrix matrix)
        {
            if (!headerWritten)
            {
                WriteHeader();
            }
            if (settings.IncludeColumnNames && !columnsWritten)
            {
                string columns = FormatColumns(matrix.NumPorts);
                WriteCommentLine(columns);
                columnsWritten = true;
            }
            string line = FormatEntry(frequency, matrix);

            Writer.WriteLine(line);
        }
        /// <summary>Asynchronously writes the frequency and <see cref="NetworkParametersMatrix"/> the network data of the file.</summary>
        /// <param name="frequency">The frequency of the network data to be written.</param>
        /// /// <param name="matrix">The network data to be written.</param>
        /// <remarks>If <see cref="WriteHeaderAsync"/> has not yet been called, this method will be called automatically before writing any network data.</remarks>
        public async Task WriteDataAsync(double frequency, NetworkParametersMatrix matrix)
        {
            if (!headerWritten)
            {
                await WriteHeaderAsync();
            }

            CancelToken.ThrowIfCancellationRequested();

            if (settings.IncludeColumnNames && !columnsWritten)
            {
                string columns = FormatColumns(matrix.NumPorts);
                await WriteCommentLineAsync(columns);

                columnsWritten = true;

                CancelToken.ThrowIfCancellationRequested();
            }
            string line = FormatEntry(frequency, matrix);
            await Writer.WriteLineAsync(line);
        }
            public override FrequencyParametersPair?ReadNextMatrix()
            {
                List <string>           rawFlattenedMatrix = new List <string>();
                FrequencyParametersPair?networkData        = default;

                if (!flattenedMatrixLength.HasValue)
                {
                    if (!tsReader.MoveToNextValidLine())
                    {
                        tsReader.ThrowHelper("Data");
                    }
                    string firstLine = tsReader.ReadLineAndCount();
                    rawFlattenedMatrix.AddRange(TrimAndSplitLine(firstLine));

                    // We only need to perform this check if the network has 2 ports or more; a one port network only has a single
                    // data pair (i.e. two entries) plus frequency. We know that we don't need to investigate subsequent lines.
                    if (rawFlattenedMatrix.Count > 3)
                    {
                        while (tsReader.MoveToNextValidLine())
                        {
                            string line = tsReader.ReadLineAndCount();
                            var    data = TrimAndSplitLine(line);
                            // Continued data lines split over multiple should always have an even number (pairs of complex data).
                            // New frequency points will have an odd number of values due to the frequency being present
                            if (data.Count % 2 == 0)
                            {
                                rawFlattenedMatrix.AddRange(data);
                            }
                            else
                            {
                                previewedLines.Enqueue(line);
                                break;
                            }
                        }
                    }
                    flattenedMatrixLength = rawFlattenedMatrix.Count;
                }
                else
                {
                    while (previewedLines.Count > 0 && rawFlattenedMatrix.Count < flattenedMatrixLength.Value)
                    {
                        string line = previewedLines.Dequeue();
                        rawFlattenedMatrix.AddRange(TrimAndSplitLine(line));
                    }
                    while (rawFlattenedMatrix.Count < flattenedMatrixLength.Value && tsReader.MoveToNextValidLine())
                    {
                        string line = tsReader.ReadLineAndCount();
                        rawFlattenedMatrix.AddRange(TrimAndSplitLine(line));
                    }
                }

                if (rawFlattenedMatrix.Count == flattenedMatrixLength.Value)
                {
                    var(frequency, parameters) = tsReader.ParseRawData(rawFlattenedMatrix);

                    NetworkParametersMatrix matrix = tsReader.Options.Parameter switch
                    {
                        ParameterType.Scattering => new ScatteringParametersMatrix(parameters, ListFormat.SourcePortMajor),
                        _ => throw new NotImplementedException($"Support for parameter type {tsReader.Options.Parameter} has not been implemented."),
                    };

                    networkData = new FrequencyParametersPair(frequency, matrix);
                }

                return(networkData);
            }