Program Listing for File arrayFromData.hpp#

Return to documentation for file (librapid/include/librapid/array/arrayFromData.hpp)

#ifndef LIBRAPID_ARRAY_FROM_DATA_HPP
#define LIBRAPID_ARRAY_FROM_DATA_HPP

namespace librapid {
    template<typename ShapeType, typename StorageType>
    LIBRAPID_ALWAYS_INLINE auto array::ArrayContainer<ShapeType, StorageType>::fromData(
      const std::initializer_list<Scalar> &data) -> ArrayContainer {
        static_assert(!std::is_same_v<ShapeType, MatrixShape>,
                      "Cannot create a matrix from a 1D array");
        LIBRAPID_ASSERT(data.size() > 0, "Array must have at least one element");
        return ArrayContainer(data);
    }

    template<typename ShapeType, typename StorageType>
    LIBRAPID_ALWAYS_INLINE auto
    array::ArrayContainer<ShapeType, StorageType>::fromData(const std::vector<Scalar> &data)
      -> ArrayContainer {
        static_assert(!std::is_same_v<ShapeType, MatrixShape>,
                      "Cannot create a matrix from a 1D array");
        LIBRAPID_ASSERT(data.size() > 0, "Array must have at least one element");
        return ArrayContainer(data);
    }

    template<typename ShapeType, typename StorageType>
    LIBRAPID_ALWAYS_INLINE auto array::ArrayContainer<ShapeType, StorageType>::fromData(
      const std::initializer_list<std::initializer_list<Scalar>> &data) -> ArrayContainer {
        LIBRAPID_ASSERT(data.size() > 0, "Cannot create a zero-sized array");

        if constexpr (std::is_same_v<ShapeType, MatrixShape>) {
            auto newShape = ShapeType({data.size(), data.begin()->size()});
            auto res      = ArrayContainer(newShape);
            for (size_t i = 0; i < data.size(); ++i) {
                LIBRAPID_ASSERT(data.begin()[i].size() == newShape[1],
                                "Arrays must have consistent shapes");
                for (size_t j = 0; j < data.begin()[i].size(); ++j) {
                    res(i, j) = data.begin()[i].begin()[j];
                }
            }
            return res;
        } else {
            auto newShape = ShapeType({data.size(), data.begin()->size()});
#if defined(LIBRAPID_ENABLE_ASSERT)
            for (size_t i = 0; i < data.size(); ++i) {
                LIBRAPID_ASSERT(data.begin()[i].size() == newShape[1],
                                "Arrays must have consistent shapes");
            }
#endif
            auto res      = ArrayContainer(newShape);
            int64_t index = 0;
            for (const auto &item : data) res[index++] = fromData(item);
            return res;
        }
    }

    template<typename ShapeType, typename StorageType>
    LIBRAPID_ALWAYS_INLINE auto array::ArrayContainer<ShapeType, StorageType>::fromData(
      const std::vector<std::vector<Scalar>> &data) -> ArrayContainer {
        LIBRAPID_ASSERT(data.size() > 0, "Cannot create a zero-sized array");

        if constexpr (std::is_same_v<ShapeType, MatrixShape>) {
            auto newShape = ShapeType({data.size(), data[0].size()});
            auto res      = ArrayContainer(newShape);
            for (size_t i = 0; i < data.size(); ++i) {
                LIBRAPID_ASSERT(data[i].size() == newShape[1],
                                "Arrays must have consistent shapes");
                for (size_t j = 0; j < data[i].size(); ++j) { res(i, j) = data[i][j]; }
            }
            return res;
        } else {
            auto newShape = ShapeType({data.size(), data.begin()->size()});
#if defined(LIBRAPID_ENABLE_ASSERT)
            for (size_t i = 0; i < data.size(); ++i) {
                LIBRAPID_ASSERT(data.begin()[i].size() == newShape[1],
                                "Arrays must have consistent shapes");
            }
#endif
            auto res      = ArrayContainer(newShape);
            int64_t index = 0;
            for (const auto &item : data) res[index++] = fromData(item);
            return res;
        }
    }

#define HIGHER_DIMENSIONAL_FROM_DATA(TYPE)                                                         \
    template<typename ShapeType, typename StorageType>                                             \
    LIBRAPID_ALWAYS_INLINE auto array::ArrayContainer<ShapeType, StorageType>::fromData(           \
      const TYPE &data) -> ArrayContainer {                                                        \
        LIBRAPID_ASSERT(data.size() > 0, "Cannot create a zero-sized array");                      \
        std::vector<ArrayContainer> tmp(data.size());                                              \
        int64_t index = 0;                                                                         \
        for (const auto &item : data) tmp[index++] = std::move(fromData(item));                    \
        auto zeroShape = tmp[0].shape();                                                           \
        for (int64_t i = 0; i < data.size(); ++i)                                                  \
            LIBRAPID_ASSERT(tmp[i].shape().operator==(zeroShape),                                  \
                            "Arrays must have consistent shapes");                                 \
        auto newShape = ShapeType::zeros(zeroShape.ndim() + 1);                                    \
        newShape[0]   = data.size();                                                               \
        for (size_t i = 0; i < zeroShape.ndim(); ++i) { newShape[i + 1] = zeroShape[i]; }          \
        auto res = Array<Scalar, Backend>(newShape);                                               \
        for (int64_t i = 0; i < data.size(); ++i) res[i] = tmp[i];                                 \
        return res;                                                                                \
    }

#define SINIT(SUB_TYPE) std::initializer_list<SUB_TYPE>
#define SVEC(SUB_TYPE)  std::vector<SUB_TYPE>

    HIGHER_DIMENSIONAL_FROM_DATA(SINIT(SINIT(SINIT(Scalar))))
    HIGHER_DIMENSIONAL_FROM_DATA(SINIT(SINIT(SINIT(SINIT(Scalar)))))
    HIGHER_DIMENSIONAL_FROM_DATA(SINIT(SINIT(SINIT(SINIT(SINIT(Scalar))))))
    HIGHER_DIMENSIONAL_FROM_DATA(SINIT(SINIT(SINIT(SINIT(SINIT(SINIT(Scalar)))))))
    HIGHER_DIMENSIONAL_FROM_DATA(SINIT(SINIT(SINIT(SINIT(SINIT(SINIT(SINIT(Scalar))))))))
    HIGHER_DIMENSIONAL_FROM_DATA(SINIT(SINIT(SINIT(SINIT(SINIT(SINIT(SINIT(SINIT(Scalar)))))))))

    HIGHER_DIMENSIONAL_FROM_DATA(SVEC(SVEC(SVEC(Scalar))))
    HIGHER_DIMENSIONAL_FROM_DATA(SVEC(SVEC(SVEC(SVEC(Scalar)))))
    HIGHER_DIMENSIONAL_FROM_DATA(SVEC(SVEC(SVEC(SVEC(SVEC(Scalar))))))
    HIGHER_DIMENSIONAL_FROM_DATA(SVEC(SVEC(SVEC(SVEC(SVEC(SVEC(Scalar)))))))
    HIGHER_DIMENSIONAL_FROM_DATA(SVEC(SVEC(SVEC(SVEC(SVEC(SVEC(SVEC(Scalar))))))))
    HIGHER_DIMENSIONAL_FROM_DATA(SVEC(SVEC(SVEC(SVEC(SVEC(SVEC(SVEC(SVEC(Scalar)))))))))

#undef SINIT
#undef HIGHER_DIMENSIONAL_FROM_DATA
} // namespace librapid

#endif // LIBRAPID_ARRAY_FROM_DATA_HPP