Пример #1
0
        private IEnumerable <IHeaderArray> BuildHeaderArrays([NotNull] FilePath file)
        {
            HeaderArrayFile arrayFile = HeaderArrayFile.BinaryReader.Read(file);

            // Variable information.
            int[] countOfComponentsInVariable = arrayFile["VNCP"].As <int>().Values.ToArray();

            // Endogenous variable components and information.
            int[]   pointersToCumulative = arrayFile["PCUM"].As <int>().Values.ToArray();
            int[]   countInCumulative    = arrayFile["CMND"].As <int>().Values.ToArray();
            float[] cumulativeResults    = arrayFile["CUMS"].As <float>().Values.ToArray();

            // Exogenous variable components and list of positions (where OREX != array.Length).
            int[] countOfExogenous     = arrayFile["OREX"].As <int>().Values.ToArray();
            int[] positionsOfExogenous = arrayFile["OREL"].As <int>().Values.ToArray();

            // Shocked variable information
            int[]   numberOfShockedComponents = arrayFile["SHCK"].As <int>().Values.ToArray();
            int[]   pointersToShockValues     = arrayFile["PSHK"].As <int>().Values.ToArray();
            int[]   positionsOfShockValues    = arrayFile["SHCL"].As <int>().Values.ToArray();
            float[] shockValues = arrayFile["SHOC"].As <float>().Values.ToArray();

            return
                (BuildSolutionArrays(arrayFile).Where(x => x.IsBacksolvedOrCondensed)
                 .OrderBy(x => x.VariableIndex)
                 .Select(BuildNextArray));

            // Local method here to limit passing arrays as parameters.
            IHeaderArray BuildNextArray(SolutionArray array, int index)
            {
                float[] values = new float[array.Count];

                // When the array is condensed/backsolved and the pointer is empty, its exogenous.
                int pointer = pointersToCumulative[index] - 1;

                if (pointer != -1)
                {
                    Array.Copy(cumulativeResults, pointer, values, 0, countInCumulative[index]);
                }

                ShiftExogenous(values);

                Shocks(values);

                return
                    (HeaderArray <float> .Create(
                         array.Name,
                         array.Name,
                         array.Description,
                         HeaderArrayType.RE,
                         array.Sets.Select(x => x.Value.Count).Concat(Enumerable.Repeat(1, 7)).Take(7),
                         values,
                         array.Sets));

                // Shifts existing entries to their appropriate positions to create gaps for exogenous values.
                void ShiftExogenous(float[] inputArray)
                {
                    if (array.Count == countOfExogenous[index])
                    {
                        Array.Clear(inputArray, 0, inputArray.Length);
                        return;
                    }

                    float[] withGaps = inputArray;

                    int nextValidPosition = 0;

                    for (int i = 0; i < index; i++)
                    {
                        if (countOfExogenous[i] != countOfComponentsInVariable[i])
                        {
                            nextValidPosition += countOfExogenous[i];
                        }
                    }

                    for (int i = 0; i < countOfExogenous[index]; i++)
                    {
                        int position = positionsOfExogenous[nextValidPosition + i] - 1;
                        Array.Copy(withGaps, position, withGaps, position + 1, withGaps.Length - position - 1);
                        withGaps[position] = default(float);
                    }
                }

                // Adds shocks to open positions to a copy of the input array.
                void Shocks(float[] inputArray)
                {
                    float[] withShocks = inputArray;

                    int shockedCount = numberOfShockedComponents[index];

                    if (shockedCount == 0)
                    {
                        return;
                    }

                    int shockPointer = pointersToShockValues[index] - 1;

                    int nextValidPosition = 0;

                    for (int i = 0; i < index - 1; i++)
                    {
                        if (numberOfShockedComponents[i] != countOfComponentsInVariable[i])
                        {
                            nextValidPosition += numberOfShockedComponents[i];
                        }
                    }

                    for (int i = 0; i < shockedCount; i++)
                    {
                        int   position = array.Count == shockedCount ? i : positionsOfShockValues[nextValidPosition + i] - 1;
                        float value    = shockValues[shockPointer + i];
                        withShocks[position] = value;
                    }
                }
            }
        }
        private static IHeaderArray ReadNext([NotNull] BinaryReader reader)
        {
            string header = GetHeader(reader);

            if (header == "ADRV")
            {
            }

            (string description, HeaderArrayStorage storage, HeaderArrayType type, int[] dimensions, int count) = GetMetadata(reader);

            switch (type)
            {
            case HeaderArrayType.C1:
            {
                // Corner case wherein the string array is really an array of single characters.
                if (dimensions[1] == 1)
                {
                    char[] values = GetOneDimensionalArray(reader, storage, count, (data, index, length) => (char)data[index]);

                    return(HeaderArray <char> .Create(header, header, description, type, dimensions, values));
                }
                else
                {
                    string[] values = GetOneDimensionalArray(reader, storage, count, (data, index, length) => Encoding.ASCII.GetString(data, index, length).Trim('\u0000', '\u0002', '\u0020'));

                    return(HeaderArray <string> .Create(header, header, description, type, dimensions, values));
                }
            }

            case HeaderArrayType.I2:
            {
                int[] values = GetTwoDimensionalArray(reader, storage, count, BitConverter.ToInt32);

                return(HeaderArray <int> .Create(header, header, description, type, dimensions, values));
            }

            case HeaderArrayType.R2:
            {
                float[] values = GetTwoDimensionalArray(reader, storage, count, BitConverter.ToSingle);

                return(HeaderArray <float> .Create(header, header, description, type, dimensions, values));
            }

            case HeaderArrayType.RE:
            {
                (string coefficient, KeyValuePair <string, IImmutableList <string> >[] sets)temp = ReadSets(reader, dimensions);

                string coefficient = temp.coefficient;
                KeyValuePair <string, IImmutableList <string> >[] sets = temp.sets;

                float[] results = GetArrayWithSets(reader, storage, count, BitConverter.ToSingle);

                return(HeaderArray <float> .Create(header, coefficient, description, type, dimensions, results, sets.ToImmutableArray()));
            }

            default:
            {
                throw new DataValidationException("An unknown header array type was encountered.", "1C, RE, 2I, 2R", type);
            }
            }
        }