Создайте новый объект внутри шаблонной функции constexpr, используя два старых объекта - PullRequest
0 голосов
/ 07 ноября 2019

Я написал шаблонный класс, который представляет Tensor (в основном матрицу), и все его операции должны быть constexpr для оценки во время компиляции.

Моя главная проблема заключается в том, что операция называется contraction, создает новый Tensor C, используя параметры из других тензорных объектов.

Этот Tensor C объединяет пакеты параметров двух других Tensors(A and B), но удаляет один индекс из одного tensor(A) и один индекс из другого tensor(B) до создания.

Isесть ли возможность сделать это, используя constexpr функции?

Следующий код - мой тензорный класс:

enum Index : int {lower = 0, upper = 1};

template<int Size, typename T>
struct Array{
    T array[Size];
    Array(const T * a){
        for(int i = 0; i < Size; i++){
            array[i] = a[i];
        }
    }
};

template<int base, int exponent>
int constexpr pow(){
    if constexpr(exponent == 0){
        return 1;
    }else{
        return base * pow<base, exponent-1>();
    }
}

template<typename T = double, auto ...IndicesN>
class TensorND{

private:
    const Array<pow<3, sizeof...(IndicesN)>(), T> matrix;
    const Index _indices[sizeof...(IndicesN)] = {IndicesN...};

public:
    constexpr TensorND(const T * arr): matrix(arr){}
    constexpr TensorND(T * arr): matrix(arr){}
};

Функция, занимающая позиции для удаления индексов и требующая двух тензоров:

template<auto removeV1, auto removeV2, typename A, typename B>
constexpr auto contraction(const A tensor1, const B tensor2){


    /*
     *code for arr later
     */
    return TensorND<  >(arr);

}

Желаемый вариант использования:

int main () {
    const double arr[27] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
                            26, 27};
    const auto tensorA = new TensorND<double, upper, upper, upper>(arr);
    const auto tensorB = new TensorND<double, lower, lower, upper>(arr);

//left "0" => remove the first upper from tensor1
//right "1" => remove the second lower from tensor2
//tensorC's parameter pack is now a combination of two parameter packs
//from left to right: upper(tensorA), upper(tensorA), lower(tensorB),upper(tensorB)
    TensorND<double, upper, upper, lower, upper> tensorC = contraction<0, 1>(tensorA, tensorB);
//or
    auto tensorC = contraction<0, 1>(tensorA, tensorB);
}
...