/*------------------------------------------------------------------------------ * Copyright (c) 2023 by Bai Bing (seread@163.com) * See COPYING file for copying and redistribution conditions. * * Alians IT Studio. *----------------------------------------------------------------------------*/ #pragma once #include #include #include #include #include "core/Error.h" #include "core/StaticAsserts.h" #include "core/TypeTraits.h" #include "utils/EssentiallyEqual.h" #include "ASMatrix.h" namespace ais { //============================================================================ // Method Description: /// Adds the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator+=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::plus()); return lhs; } //============================================================================ // Method Description: /// Adds the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator+=(Matrix> &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](std::complex &val1, dtype val2) -> std::complex { return val1 + val2; }; std::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function); return lhs; } //============================================================================ // Method Description: /// Adds the scaler to the array (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator+=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype &value) -> dtype { return value += rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Adds the scaler to the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator+=(Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex &value) -> std::complex { return value += rhs; }; std::for_each(lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Adds the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator+(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); std::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::plus()); return returnArray; } //============================================================================ // Method Description: /// Adds the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator+(const Matrix &lhs, const Matrix> &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](dtype val1, const std::complex &val2) -> std::complex { return val1 + val2; }; Matrix> returnArray(lhs.shape()); std::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Adds the elements of two arrays (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator+(const Matrix> &lhs, const Matrix &rhs) { return rhs + lhs; } //============================================================================ // Method Description: /// Adds the scaler to the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator+(const Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype value) -> dtype { return value + rhs; }; Matrix returnArray(lhs.shape()); std::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Adds the scaler to the array (5) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator+(dtype lhs, const Matrix &rhs) { return rhs + lhs; } //============================================================================ // Method Description: /// Adds the scaler to the array (6) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator+(const Matrix &lhs, const std::complex &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](dtype value) -> std::complex { return value + rhs; }; Matrix> returnArray(lhs.shape()); std::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Adds the scaler to the array (7) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator+(const std::complex &lhs, const Matrix &rhs) { return rhs + lhs; } //============================================================================ // Method Description: /// Adds the scaler to the array (8) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator+(const Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex value) -> std::complex { return value + rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Adds the scaler to the array (9) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator+(dtype lhs, const Matrix> &rhs) { return rhs + lhs; } //============================================================================ // Method Description: /// Subtracts the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator-=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::minus()); return lhs; } //============================================================================ // Method Description: /// Subtracts the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator-=(Matrix> &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](std::complex &val1, dtype val2) -> std::complex { return val1 - val2; }; std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function); return lhs; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator-=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype &value) -> dtype { return value -= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator-=(Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex &value) -> std::complex { return value -= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Subtracts the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator-(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::minus()); return returnArray; } //============================================================================ // Method Description: /// Subtracts the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator-(const Matrix &lhs, const Matrix> &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](dtype val1, const std::complex &val2) -> std::complex { return val1 - val2; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the elements of two arrays (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator-(const Matrix> &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](const std::complex &val1, dtype val2) -> std::complex { return val1 - val2; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator-(const Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype value) -> dtype { return value - rhs; }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (5) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator-(dtype lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [lhs](dtype value) -> dtype { return lhs - value; }; Matrix returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.cbegin(), rhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (6) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator-(const Matrix &lhs, const std::complex &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](dtype value) -> std::complex { return value - rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (7) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator-(const std::complex &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [lhs](dtype value) -> std::complex { return lhs - value; }; Matrix> returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.cbegin(), rhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (8) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator-(const Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex value) -> std::complex { return value - rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Subtracts the scaler from the array (9) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator-(dtype lhs, const Matrix> &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [lhs](std::complex value) -> std::complex { return lhs - value; }; Matrix> returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.cbegin(), rhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Negative Operator /// /// @return Matrix /// template AIS_EXPORT Matrix operator-(const Matrix &inArray) { const auto function = [](dtype value) -> dtype { return -value; }; auto returnArray = Matrix(inArray.shape()); std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Multiplies the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator*=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::multiplies()); return lhs; } //============================================================================ // Method Description: /// Multiplies the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator*=(Matrix> &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](std::complex &val1, dtype val2) -> std::complex { return val1 * val2; }; std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function); return lhs; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator*=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype &value) -> dtype { return value *= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator*=(Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex &value) -> std::complex { return value *= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Multiplies the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator*(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::multiplies()); return returnArray; } //============================================================================ // Method Description: /// Multiplies the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator*(const Matrix &lhs, const Matrix> &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](dtype val1, const std::complex &val2) -> std::complex { return val1 * val2; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Multiplies the elements of two arrays (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator*(const Matrix> &lhs, const Matrix &rhs) { return rhs * lhs; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator*(const Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype value) -> dtype { return value * rhs; }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (5) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator*(dtype lhs, const Matrix &rhs) { return rhs * lhs; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (6) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator*(const Matrix &lhs, const std::complex &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](dtype value) -> std::complex { return value * rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (7) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator*(const std::complex &lhs, const Matrix &rhs) { return rhs * lhs; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (8) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator*(const Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex value) -> std::complex { return value * rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Multiplies the scaler to the array (9) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator*(dtype lhs, const Matrix> &rhs) { return rhs * lhs; } //============================================================================ // Method Description: /// Divides the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator/=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::divides()); return lhs; } //============================================================================ // Method Description: /// Divides the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator/=(Matrix> &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](std::complex &val1, dtype val2) -> std::complex { return val1 / val2; }; std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function); return lhs; } //============================================================================ // Method Description: /// Divides the scaler from the array (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator/=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype &value) -> dtype { return value /= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Divides the scaler from the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> &operator/=(Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex &value) -> std::complex { return value /= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Divides the elements of two arrays (1) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator/(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::divides()); return returnArray; } //============================================================================ // Method Description: /// Divides the elements of two arrays (2) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator/(const Matrix &lhs, const Matrix> &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix> returnArray(lhs.shape()); const auto function = [](dtype val1, const std::complex &val2) -> std::complex { return val1 / val2; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the elements of two arrays (3) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator/(const Matrix> &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](const std::complex &val1, dtype val2) -> std::complex { return val1 / val2; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the scaler from the array (4) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator/(const Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [rhs](dtype value) -> dtype { return value / rhs; }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the scaler from the array (5) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator/(dtype lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); const auto function = [lhs](dtype value) -> dtype { return lhs / value; }; Matrix returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.cbegin(), rhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the scaler from the array (6) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator/(const Matrix &lhs, const std::complex &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](dtype value) -> std::complex { return value / rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the scaler from the array (7) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator/(const std::complex &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [lhs](dtype value) -> std::complex { return lhs / value; }; Matrix> returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.cbegin(), rhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the scaler from the array (8) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator/(const Matrix> &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [rhs](std::complex value) -> std::complex { return value / rhs; }; Matrix> returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Divides the scaler from the array (9) /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix> operator/(dtype lhs, const Matrix> &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [lhs](std::complex value) -> std::complex { return lhs / value; }; Matrix> returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.cbegin(), rhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Modulus the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template ::value, int> = 0> AIS_EXPORT Matrix &operator%=(Matrix &lhs, const Matrix &rhs) { if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::modulus()); return lhs; } //============================================================================ // Method Description: /// Modulus the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template ::value, int> = 0> AIS_EXPORT Matrix &operator%=(Matrix &lhs, const Matrix &rhs) { if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](const dtype value1, const dtype value2) -> dtype { return std::fmod(value1, value2); }; std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function); return lhs; } //============================================================================ // Method Description: /// Modulus the scaler to the array /// /// @param lhs /// @param rhs /// @return Matrix /// template ::value, int> = 0> AIS_EXPORT Matrix &operator%=(Matrix &lhs, dtype rhs) { const auto function = [rhs](dtype &value) -> dtype { return value %= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Modulus the scaler to the array /// /// @param lhs /// @param rhs /// @return Matrix /// template ::value, int> = 0> AIS_EXPORT Matrix &operator%=(Matrix &lhs, dtype rhs) { const auto function = [rhs](dtype &value) -> void { value = std::fmod(value, rhs); }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Takes the modulus of the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator%(const Matrix &lhs, const Matrix &rhs) { auto returnArray = Matrix(lhs); returnArray %= rhs; return returnArray; } //============================================================================ // Method Description: /// Modulus of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator%(const Matrix &lhs, dtype rhs) { auto returnArray = Matrix(lhs); returnArray %= rhs; return returnArray; } //============================================================================ // Method Description: /// Modulus of the scaler and the array /// /// @param lhs /// @param rhs /// @return Matrix /// template ::value, int> = 0> AIS_EXPORT Matrix operator%(dtype lhs, const Matrix &rhs) { Matrix returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.begin(), rhs.end(), returnArray.begin(), [lhs](dtype value) -> dtype { return lhs % value; }); return returnArray; } //============================================================================ // Method Description: /// Modulus of the scaler and the array /// /// @param lhs /// @param rhs /// @return Matrix /// template ::value, int> = 0> AIS_EXPORT Matrix operator%(dtype lhs, const Matrix &rhs) { Matrix returnArray(rhs.shape()); std::transform(std::execution::par_unseq, rhs.begin(), rhs.end(), returnArray.begin(), [lhs](dtype value) -> dtype { return std::fmod(lhs, value); }); return returnArray; } //============================================================================ // Method Description: /// Bitwise or the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator|=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_INTEGER(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::bit_or()); return lhs; } //============================================================================ // Method Description: /// Bitwise or the scaler to the array /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator|=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_INTEGER(dtype); const auto function = [rhs](dtype &value) -> dtype { return value |= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Takes the bitwise or of the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator|(const Matrix &lhs, const Matrix &rhs) { auto returnArray = Matrix(lhs); returnArray |= rhs; return returnArray; } //============================================================================ // Method Description: /// Takes the bitwise or of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator|(const Matrix &lhs, dtype rhs) { auto returnArray = Matrix(lhs); returnArray |= rhs; return returnArray; } //============================================================================ // Method Description: /// Takes the bitwise or of the sclar and the array /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator|(dtype lhs, const Matrix &rhs) { return rhs | lhs; } //============================================================================ // Method Description: /// Bitwise and the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator&=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_INTEGER(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::bit_and()); return lhs; } //============================================================================ // Method Description: /// Bitwise and the scaler to the array /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator&=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_INTEGER(dtype); const auto function = [rhs](dtype &value) -> dtype { return value &= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Takes the bitwise and of the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator&(const Matrix &lhs, const Matrix &rhs) { auto returnArray = Matrix(lhs); returnArray &= rhs; return returnArray; } //============================================================================ // Method Description: /// Takes the bitwise and of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator&(const Matrix &lhs, dtype rhs) { auto returnArray = Matrix(lhs); returnArray &= rhs; return returnArray; } //============================================================================ // Method Description: /// Takes the bitwise and of the sclar and the array /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator&(dtype lhs, const Matrix &rhs) { return rhs & lhs; } //============================================================================ // Method Description: /// Bitwise xor the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator^=(Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_INTEGER(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } std::transform(std::execution::par_unseq, lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::bit_xor()); return lhs; } //============================================================================ // Method Description: /// Bitwise xor the scaler to the array /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix &operator^=(Matrix &lhs, dtype rhs) { STATIC_ASSERT_INTEGER(dtype); const auto function = [rhs](dtype &value) -> dtype { return value ^= rhs; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Takes the bitwise xor of the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator^(const Matrix &lhs, const Matrix &rhs) { auto returnArray = Matrix(lhs); returnArray ^= rhs; return returnArray; } //============================================================================ // Method Description: /// Takes the bitwise xor of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator^(const Matrix &lhs, dtype rhs) { auto returnArray = Matrix(lhs); returnArray ^= rhs; return returnArray; } //============================================================================ // Method Description: /// Takes the bitwise xor of the sclar and the array /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator^(dtype lhs, const Matrix &rhs) { return rhs ^ lhs; } //============================================================================ // Method Description: /// Takes the bitwise not of the array /// /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator~(const Matrix &inArray) { STATIC_ASSERT_INTEGER(dtype); const auto function = [](dtype value) -> dtype { return ~value; }; Matrix returnArray(inArray.shape()); std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Takes the and of the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator&&(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](dtype value1, dtype value2) -> bool { return value1 && value2; }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Takes the and of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator&&(const Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); Matrix returnArray(lhs.shape()); const auto function = [rhs](dtype value) -> bool { return value && rhs; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Takes the and of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator&&(dtype lhs, const Matrix &rhs) { return rhs && lhs; } //============================================================================ // Method Description: /// Takes the or of the elements of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator||(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto function = [](dtype value1, dtype value2) -> bool { return value1 || value2; }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Takes the or of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator||(const Matrix &lhs, dtype rhs) { STATIC_ASSERT_ARITHMETIC(dtype); Matrix returnArray(lhs.shape()); const auto function = [rhs](dtype value) -> bool { return value || rhs; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Takes the or of the array and the scaler /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator||(dtype lhs, const Matrix &rhs) { return rhs || lhs; } //============================================================================ // Method Description: /// Takes the not of the array /// /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator!(const Matrix &inArray) { STATIC_ASSERT_ARITHMETIC(dtype); Matrix returnArray(inArray.shape()); const auto function = [](dtype value) -> dtype { return !value; }; std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator==(const Matrix &lhs, const Matrix &rhs) { if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto equalTo = [](dtype lhs, dtype rhs) noexcept -> bool { return utils::essentially_equal(lhs, rhs); }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), equalTo); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// an array and a scaler /// /// @param lhs /// @param inValue /// @return Matrix /// template AIS_EXPORT Matrix operator==(const Matrix &lhs, dtype inValue) { Matrix returnArray(lhs.shape()); const auto equalTo = [inValue](dtype value) noexcept -> bool { return utils::essentially_equal(inValue, value); }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), equalTo); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// an array and a scaler /// /// @param inValue /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator==(dtype inValue, const Matrix &inArray) { return inArray == inValue; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator!=(const Matrix &lhs, const Matrix &rhs) { if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } const auto notEqualTo = [](dtype lhs, dtype rhs) noexcept -> bool { return !utils::essentially_equal(lhs, rhs); }; Matrix returnArray(lhs.shape()); std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), notEqualTo); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// an array and a scaler /// /// @param lhs /// @param inValue /// @return Matrix /// template AIS_EXPORT Matrix operator!=(const Matrix &lhs, dtype inValue) { Matrix returnArray(lhs.shape()); const auto notEqualTo = [inValue](dtype value) noexcept -> bool { return !utils::essentially_equal(inValue, value); }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), notEqualTo); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// an array and a scaler /// /// @param inValue /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator!=(dtype inValue, const Matrix &inArray) { return inArray != inValue; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator<(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param lhs /// @param inValue /// @return Matrix /// template AIS_EXPORT Matrix operator<(const Matrix &lhs, dtype inValue) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(lhs.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return value < inValue; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param inValue /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator<(dtype inValue, const Matrix &inArray) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(inArray.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return inValue < value; }; std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator>(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs > rhs; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param lhs /// @param inValue /// @return Matrix /// template AIS_EXPORT Matrix operator>(const Matrix &lhs, dtype inValue) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(lhs.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return value > inValue; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param inValue /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator>(dtype inValue, const Matrix &inArray) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(inArray.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return inValue > value; }; std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator<=(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs <= rhs; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param lhs /// @param inValue /// @return Matrix /// template AIS_EXPORT Matrix operator<=(const Matrix &lhs, dtype inValue) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(lhs.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return value <= inValue; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param inValue /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator<=(dtype inValue, const Matrix &inArray) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(inArray.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return inValue <= value; }; std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// of two arrays /// /// @param lhs /// @param rhs /// @return Matrix /// template AIS_EXPORT Matrix operator>=(const Matrix &lhs, const Matrix &rhs) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); if (lhs.shape() != rhs.shape()) { THROW_INVALID_ARGUMENT("Array dimensions do not match."); } Matrix returnArray(lhs.shape()); const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs >= rhs; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param lhs /// @param inValue /// @return Matrix /// template AIS_EXPORT Matrix operator>=(const Matrix &lhs, dtype inValue) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(lhs.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return value >= inValue; }; std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Returns an array of booleans of element wise comparison /// the array and a scaler /// /// @param inValue /// @param inArray /// @return Matrix /// template AIS_EXPORT Matrix operator>=(dtype inValue, const Matrix &inArray) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); Matrix returnArray(inArray.shape()); const auto function = [inValue](dtype value) noexcept -> bool { return inValue >= value; }; std::transform(std::execution::par_unseq, inArray.cbegin(), inArray.cend(), returnArray.begin(), function); return returnArray; } //============================================================================ // Method Description: /// Bitshifts left the elements of the array /// /// @param lhs /// @param inNumBits /// @return Matrix /// template AIS_EXPORT Matrix &operator<<=(Matrix &lhs, uint8_t inNumBits) { STATIC_ASSERT_INTEGER(dtype); const auto function = [inNumBits](dtype &value) -> void { value <<= inNumBits; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Bitshifts left the elements of the array /// /// @param lhs /// @param inNumBits /// @return Matrix /// template AIS_EXPORT Matrix operator<<(const Matrix &lhs, uint8_t inNumBits) { STATIC_ASSERT_INTEGER(dtype); Matrix returnArray(lhs); returnArray <<= inNumBits; return returnArray; } //============================================================================ // Method Description: /// Bitshifts right the elements of the array /// /// @param lhs /// @param inNumBits /// @return Matrix /// template AIS_EXPORT Matrix &operator>>=(Matrix &lhs, uint8_t inNumBits) { STATIC_ASSERT_INTEGER(dtype); const auto function = [inNumBits](dtype &value) -> void { value >>= inNumBits; }; std::for_each(std::execution::par_unseq, lhs.begin(), lhs.end(), function); return lhs; } //============================================================================ // Method Description: /// Bitshifts right the elements of the array /// /// @param lhs /// @param inNumBits /// @return Matrix /// template AIS_EXPORT Matrix operator>>(const Matrix &lhs, uint8_t inNumBits) { STATIC_ASSERT_INTEGER(dtype); Matrix returnArray(lhs); returnArray >>= inNumBits; return returnArray; } //============================================================================ // Method Description: /// prefix incraments the elements of an array /// /// @return Matrix /// template AIS_EXPORT Matrix &operator++(Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [](dtype &value) -> void { ++value; }; std::for_each(std::execution::par_unseq, rhs.begin(), rhs.end(), function); return rhs; } //============================================================================ // Method Description: /// postfix increments the elements of an array /// /// @param lhs /// @return Matrix /// template AIS_EXPORT Matrix operator++(Matrix &lhs, int) { auto copy = Matrix(lhs); ++lhs; return copy; } //============================================================================ // Method Description: /// prefix decrements the elements of an array /// /// @return Matrix /// template AIS_EXPORT Matrix &operator--(Matrix &rhs) { STATIC_ASSERT_ARITHMETIC(dtype); const auto function = [](dtype &value) -> void { --value; }; std::for_each(std::execution::par_unseq, rhs.begin(), rhs.end(), function); return rhs; } //============================================================================ // Method Description: /// postfix decrements the elements of an array /// /// @param lhs /// @return Matrix /// template AIS_EXPORT Matrix operator--(Matrix &lhs, int) { auto copy = Matrix(lhs); --lhs; return copy; } //============================================================================ // Method Description: /// io operator for the Matrix class /// /// @param inOStream /// @param inArray /// @return std::ostream /// template AIS_EXPORT std::ostream &operator<<(std::ostream &inOStream, const Matrix &inArray) { STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype); inOStream << inArray.str(); return inOStream; } } // namespace ais