<commit_before>//=======================================================================
// Copyright (c) 2014 <NAME>
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_MULTIPLICATION_HPP
#define ETL_MULTIPLICATION_HPP

#include <algorithm>

namespace etl {

namespace detail {

template<typename A, typename B, typename C, cpp::disable_if_all_u<etl_traits<A>::is_fast, etl_traits<B>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_mmul_sizes(const A& a, const B& b, C& c){
    cpp_assert(
            dim<1>(a) == dim<0>(b)          //interior dimensions
        &&  dim<0>(a) == dim<0>(c)          //exterior dimension 1
        &&  dim<1>(b) == dim<1>(c),         //exterior dimension 2
        "Invalid sizes for multiplication");
    cpp_unused(a);
    cpp_unused(b);
    cpp_unused(c);
}

template<typename A, typename B, typename C, cpp::enable_if_all_u<etl_traits<A>::is_fast, etl_traits<B>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_mmul_sizes(const A&, const B&, C&){
    static_assert(
            etl_traits<A>::template dim<1>() == etl_traits<B>::template dim<0>()          //interior dimensions
        &&  etl_traits<A>::template dim<0>() == etl_traits<C>::template dim<0>()          //exterior dimension 1
        &&  etl_traits<B>::template dim<1>() == etl_traits<C>::template dim<1>(),         //exterior dimension 2
        "Invalid sizes for multiplication");
}

} //end of namespace detail

template<typename A, typename B, typename C>
static C& mmul(const A& a, const B& b, C& c){
    static_assert(is_etl_expr<A>::value && is_etl_expr<B>::value && is_etl_expr<C>::value, "Matrix multiplication only supported for ETL expressions");
    static_assert(etl_traits<A>::dimensions() == 2 && etl_traits<B>::dimensions() == 2 && etl_traits<C>::dimensions() == 2, "Matrix multiplication only works in 2D");
    detail::check_mmul_sizes(a,b,c);

    c = 0;

    for(std::size_t i = 0; i < rows(a); i++){
        for(std::size_t j = 0; j < columns(b); j++){
            for(std::size_t k = 0; k < columns(a); k++){
                c(i,j) += a(i,k) * b(k,j);
            }
        }
    }

    return c;
}

inline std::size_t nextPowerOfTwo(std::size_t n) {
    return std::pow(2, static_cast<std::size_t>(std::ceil(std::log2(n))));
}

template<typename A, typename B, typename C>
static void strassen_mmul_r(const A& a, const B& b, C& c){
    using type = typename A::value_type;

    auto n = dim<0>(a);

    //1x1 matrix mul
    if (n == 1) {
        c(0,0) = a(0,0) * b(0,0);
    } else {
        auto new_n = n / 2;

        etl::dyn_matrix<type> a11(new_n, new_n);
        etl::dyn_matrix<type> a12(new_n, new_n);
        etl::dyn_matrix<type> a21(new_n, new_n);
        etl::dyn_matrix<type> a22(new_n, new_n);

        etl::dyn_matrix<type> b11(new_n, new_n);
        etl::dyn_matrix<type> b12(new_n, new_n);
        etl::dyn_matrix<type> b21(new_n, new_n);
        etl::dyn_matrix<type> b22(new_n, new_n);

        etl::dyn_matrix<type> p1(new_n, new_n);
        etl::dyn_matrix<type> p2(new_n, new_n);
        etl::dyn_matrix<type> p3(new_n, new_n);
        etl::dyn_matrix<type> p4(new_n, new_n);
        etl::dyn_matrix<type> p5(new_n, new_n);

        for (std::size_t i = 0; i < new_n; i++) {<commit_msg>Do n==2 without allocations<commit_after>//=======================================================================
// Copyright (c) 2014 <NAME>
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_MULTIPLICATION_HPP
#define ETL_MULTIPLICATION_HPP

#include <algorithm>

namespace etl {

namespace detail {

template<typename A, typename B, typename C, cpp::disable_if_all_u<etl_traits<A>::is_fast, etl_traits<B>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_mmul_sizes(const A& a, const B& b, C& c){
    cpp_assert(
            dim<1>(a) == dim<0>(b)          //interior dimensions
        &&  dim<0>(a) == dim<0>(c)          //exterior dimension 1
        &&  dim<1>(b) == dim<1>(c),         //exterior dimension 2
        "Invalid sizes for multiplication");
    cpp_unused(a);
    cpp_unused(b);
    cpp_unused(c);
}

template<typename A, typename B, typename C, cpp::enable_if_all_u<etl_traits<A>::is_fast, etl_traits<B>::is_fast, etl_traits<C>::is_fast> = cpp::detail::dummy>
void check_mmul_sizes(const A&, const B&, C&){
    static_assert(
            etl_traits<A>::template dim<1>() == etl_traits<B>::template dim<0>()          //interior dimensions
        &&  etl_traits<A>::template dim<0>() == etl_traits<C>::template dim<0>()          //exterior dimension 1
        &&  etl_traits<B>::template dim<1>() == etl_traits<C>::template dim<1>(),         //exterior dimension 2
        "Invalid sizes for multiplication");
}

} //end of namespace detail

template<typename A, typename B, typename C>
static C& mmul(const A& a, const B& b, C& c){
    static_assert(is_etl_expr<A>::value && is_etl_expr<B>::value && is_etl_expr<C>::value, "Matrix multiplication only supported for ETL expressions");
    static_assert(etl_traits<A>::dimensions() == 2 && etl_traits<B>::dimensions() == 2 && etl_traits<C>::dimensions() == 2, "Matrix multiplication only works in 2D");
    detail::check_mmul_sizes(a,b,c);

    c = 0;

    for(std::size_t i = 0; i < rows(a); i++){
        for(std::size_t j = 0; j < columns(b); j++){
            for(std::size_t k = 0; k < columns(a); k++){
                c(i,j) += a(i,k) * b(k,j);
            }
        }
    }

    return c;
}

inline std::size_t nextPowerOfTwo(std::size_t n) {
    return std::pow(2, static_cast<std::size_t>(std::ceil(std::log2(n))));
}

template<typename A, typename B, typename C>
static void strassen_mmul_r(const A& a, const B& b, C& c){
    using type = typename A::value_type;

    auto n = dim<0>(a);

    //1x1 matrix mul
    if (n == 1) {
        c(0,0) = a(0,0) * b(0,0);
    } else if(n == 2){
        auto a11 = a(0,0);
        auto a12 = a(0,1);
        auto a21 = a(1,0);
        auto a22 = a(1,1);

        auto b11 = b(0,0);
        auto b12 = b(0,1);
        auto b21 = b(1,0);
        auto b22 = b(1,1);

        auto p1 = (a11 + a22) * (b11 + b22);
        auto p2 = (a12 - a22) * (b21 + b22);
        auto p3 = a11 * (b12 - b22);
        auto p4 = a22 * (b21 - b11);
        auto p5 = (a11 + a12) * b22;
        auto p6 = (a21 + a22) * b11;
        auto p7 = (a21 - a11) * (b11 + b12);

        c(0,0) = p1 + p4 + p2 - p5;
        c(0,1) = p3 + p5;
        c(1,0) = p6 + p4;
        c(1,1) = p1 + p3 + p7 - p6;
    } else {
        auto new_n = n / 2;

        etl::dyn_matrix<type> a11(new_n, new_n);
        etl::dyn_matrix<type> a12(new_n, new_n);
        etl::dyn_matrix<type> a21(new_n, new_n);
        etl::dyn_matrix<type> a22(new_n, new_n);

        etl::dyn_matrix<type> b11(new_n, new_n);
        etl::dyn_matrix<type> b12(new_n, new_n);
        etl::dyn_matrix<type> b21(new_n, new_n);
        etl::dyn_matrix<type> b22(new_n, new_n);

        etl::dyn_matrix<type> p1(new_n, new_n);
        etl::dyn_matrix<type> p2(new_n, new_n);
        etl::dyn_matrix<type> p3(new_n, new_n);
        etl::dyn_matrix<type> p4(new_n, new_n);
        etl::dyn_matrix<type> p5(new_n, new_n);

        for (std::size_t i = 0; i < new_n; i++) {
{'fraction_non_alphanumeric': 0.20296570898980537, 'fraction_numerical': 0.031113464848404607, 'mean_word_length': 3.1323851203501096, 'pattern_counts': {'":': 0, '<': 117, '<?xml version=': 0, '>': 109, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '219759', 'n_tokens_mistral': 3016, 'n_tokens_neox': 2821, 'n_words': 626}