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); } } }