/// <summary>
        /// Create a new cell array.
        /// </summary>
        /// <param name="dimensions">Dimensions of the array.</param>
        /// <returns>A cell array of given dimensions, consisting of empty arrays.</returns>
        public ICellArray NewCellArray(params int[] dimensions)
        {
            var flags    = ConstructArrayFlags(ArrayType.MxCell);
            var elements = Enumerable.Repeat(MatArray.Empty() as IArray, dimensions.NumberOfElements()).ToList();

            return(new MatCellArray(flags, dimensions, string.Empty, elements));
        }
        /// <summary>
        /// Create a new structure array.
        /// </summary>
        /// <param name="fields">Names of structure fields.</param>
        /// <param name="dimensions">Dimensions of the array.</param>
        /// <returns>A structure array of given dimensions with given fields, consisting of empty arrays.</returns>
        public IStructureArray NewStructureArray(IEnumerable <string> fields, params int[] dimensions)
        {
            var flags      = ConstructArrayFlags(ArrayType.MxStruct);
            var elements   = Enumerable.Repeat(MatArray.Empty() as IArray, dimensions.NumberOfElements()).ToList();
            var dictionary = new Dictionary <string, List <IArray> >();

            foreach (var field in fields)
            {
                dictionary[field] = elements.ToList();
            }
            return(new MatStructureArray(flags, dimensions, string.Empty, dictionary));
        }
        private DataElement ReadMatrix(Tag tag, BinaryReader reader)
        {
            if (tag.Length == 0)
            {
                return(MatArray.Empty());
            }

            var element1 = Read(reader);
            var flags    = ReadArrayFlags(element1);

            if (flags.Class == ArrayType.MxOpaque)
            {
                return(ContinueReadingOpaque(reader));
            }

            var element2 = Read(reader) as MiNum <int> ??
                           throw new HandlerException("Unexpected type in array dimensions data.");
            var dimensions = ReadDimensionsArray(element2);
            var element3   = Read(reader) as MiNum <sbyte> ?? throw new HandlerException("Unexpected type in array name.");
            var name       = ReadName(element3);

            if (flags.Class == ArrayType.MxCell)
            {
                return(ContinueReadingCellArray(reader, flags, dimensions, name));
            }

            if (flags.Class == ArrayType.MxSparse)
            {
                return(ContinueReadingSparseArray(reader, element1, dimensions, name));
            }

            var         element4      = Read(reader);
            var         data          = ReadData(element4);
            DataElement imaginaryData = null;

            if (flags.Variable.HasFlag(Variable.IsComplex))
            {
                var element5 = Read(reader);
                imaginaryData = ReadData(element5);
            }

            if (flags.Class == ArrayType.MxStruct)
            {
                var fieldNameLengthElement = data as MiNum <int> ??
                                             throw new HandlerException(
                                                       "Unexpected type in structure field name length.");
                return(ContinueReadingStructure(reader, flags, dimensions, name, fieldNameLengthElement.Data[0]));
            }

            switch (flags.Class)
            {
            case ArrayType.MxChar:
                switch (data)
                {
                case MiNum <byte> _:
                    return(DataElementConverter.ConvertToMatNumericalArrayOf <byte>(
                               flags,
                               dimensions,
                               name,
                               data,
                               imaginaryData));

                case MiNum <ushort> _:
                    return(DataElementConverter.ConvertToMatNumericalArrayOf <ushort>(
                               flags,
                               dimensions,
                               name,
                               data,
                               imaginaryData));

                default:
                    throw new NotSupportedException(
                              $"This type of char array ({data.GetType()}) is not supported.");
                }

            case ArrayType.MxInt8:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <sbyte>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxUInt8:
                if (flags.Variable.HasFlag(Variable.IsLogical))
                {
                    return(DataElementConverter.ConvertToMatNumericalArrayOf <bool>(
                               flags,
                               dimensions,
                               name,
                               data,
                               imaginaryData));
                }

                return(DataElementConverter.ConvertToMatNumericalArrayOf <byte>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxInt16:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <short>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxUInt16:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <ushort>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxInt32:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <int>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxUInt32:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <uint>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxInt64:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <long>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxUInt64:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <ulong>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxSingle:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <float>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            case ArrayType.MxDouble:
                return(DataElementConverter.ConvertToMatNumericalArrayOf <double>(
                           flags,
                           dimensions,
                           name,
                           data,
                           imaginaryData));

            default:
                throw new HandlerException("Unknown data type.");
            }
        }
 /// <summary>
 /// Create a new empty array.
 /// </summary>
 /// <returns>An empty array.</returns>
 public IArray NewEmpty()
 {
     return(MatArray.Empty());
 }