You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2399 lines
72 KiB
C++

/*------------------------------------------------------------------------------
* Copyright (c) 2023 by Bai Bing (seread@163.com)
* See COPYING file for copying and redistribution conditions.
*
* Alians IT Studio.
*----------------------------------------------------------------------------*/
#pragma once
#include <algorithm>
#include <cmath>
#include <complex>
#include <functional>
#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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator+=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Adds the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator+=(Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
const auto function = [](std::complex<dtype> &val1, dtype val2) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator+=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator+=(Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> &value) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator+(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<dtype> returnArray(lhs.shape());
std::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::plus<dtype>());
return returnArray;
}
//============================================================================
// Method Description:
/// Adds the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator+(const Matrix<dtype> &lhs, const Matrix<std::complex<dtype>> &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<dtype> &val2) -> std::complex<dtype>
{ return val1 + val2; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator+(const Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
return rhs + lhs;
}
//============================================================================
// Method Description:
/// Adds the scaler to the array (4)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator+(const Matrix<dtype> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
const auto function = [rhs](dtype value) -> dtype
{ return value + rhs; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator+(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs + lhs;
}
//============================================================================
// Method Description:
/// Adds the scaler to the array (6)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator+(const Matrix<dtype> &lhs, const std::complex<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](dtype value) -> std::complex<dtype>
{ return value + rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator+(const std::complex<dtype> &lhs, const Matrix<dtype> &rhs)
{
return rhs + lhs;
}
//============================================================================
// Method Description:
/// Adds the scaler to the array (8)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator+(const Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
{ return value + rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator+(dtype lhs, const Matrix<std::complex<dtype>> &rhs)
{
return rhs + lhs;
}
//============================================================================
// Method Description:
/// Subtracts the elements of two arrays (1)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator-=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Subtracts the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator-=(Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
const auto function = [](std::complex<dtype> &val1, dtype val2) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator-=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator-=(Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> &value) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator-(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<dtype> returnArray(lhs.shape());
std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::minus<dtype>());
return returnArray;
}
//============================================================================
// Method Description:
/// Subtracts the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator-(const Matrix<dtype> &lhs, const Matrix<std::complex<dtype>> &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<dtype> &val2) -> std::complex<dtype>
{ return val1 - val2; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator-(const Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
const auto function = [](const std::complex<dtype> &val1, dtype val2) -> std::complex<dtype>
{ return val1 - val2; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator-(const Matrix<dtype> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
const auto function = [rhs](dtype value) -> dtype
{ return value - rhs; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator-(dtype lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
const auto function = [lhs](dtype value) -> dtype
{ return lhs - value; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator-(const Matrix<dtype> &lhs, const std::complex<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](dtype value) -> std::complex<dtype>
{ return value - rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator-(const std::complex<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [lhs](dtype value) -> std::complex<dtype>
{ return lhs - value; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator-(const Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
{ return value - rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator-(dtype lhs, const Matrix<std::complex<dtype>> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [lhs](std::complex<dtype> value) -> std::complex<dtype>
{ return lhs - value; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator-(const Matrix<dtype> &inArray)
{
const auto function = [](dtype value) -> dtype
{ return -value; };
auto returnArray = Matrix<dtype>(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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator*=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Multiplies the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator*=(Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
const auto function = [](std::complex<dtype> &val1, dtype val2) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator*=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator*=(Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> &value) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator*(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<dtype> returnArray(lhs.shape());
std::transform(std::execution::par_unseq, lhs.cbegin(),
lhs.cend(),
rhs.cbegin(),
returnArray.begin(),
std::multiplies<dtype>());
return returnArray;
}
//============================================================================
// Method Description:
/// Multiplies the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator*(const Matrix<dtype> &lhs, const Matrix<std::complex<dtype>> &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<dtype> &val2) -> std::complex<dtype>
{ return val1 * val2; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator*(const Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
return rhs * lhs;
}
//============================================================================
// Method Description:
/// Multiplies the scaler to the array (4)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator*(const Matrix<dtype> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
const auto function = [rhs](dtype value) -> dtype
{ return value * rhs; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator*(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs * lhs;
}
//============================================================================
// Method Description:
/// Multiplies the scaler to the array (6)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator*(const Matrix<dtype> &lhs, const std::complex<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](dtype value) -> std::complex<dtype>
{ return value * rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator*(const std::complex<dtype> &lhs, const Matrix<dtype> &rhs)
{
return rhs * lhs;
}
//============================================================================
// Method Description:
/// Multiplies the scaler to the array (8)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator*(const Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
{ return value * rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator*(dtype lhs, const Matrix<std::complex<dtype>> &rhs)
{
return rhs * lhs;
}
//============================================================================
// Method Description:
/// Divides the elements of two arrays (1)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator/=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Divides the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator/=(Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
const auto function = [](std::complex<dtype> &val1, dtype val2) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator/=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> &operator/=(Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> &value) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator/(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<dtype> returnArray(lhs.shape());
std::transform(std::execution::par_unseq, lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::divides<dtype>());
return returnArray;
}
//============================================================================
// Method Description:
/// Divides the elements of two arrays (2)
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator/(const Matrix<dtype> &lhs, const Matrix<std::complex<dtype>> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<std::complex<dtype>> returnArray(lhs.shape());
const auto function = [](dtype val1, const std::complex<dtype> &val2) -> std::complex<dtype>
{ 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator/(const Matrix<std::complex<dtype>> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
const auto function = [](const std::complex<dtype> &val1, dtype val2) -> std::complex<dtype>
{ return val1 / val2; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator/(const Matrix<dtype> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
const auto function = [rhs](dtype value) -> dtype
{ return value / rhs; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator/(dtype lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
const auto function = [lhs](dtype value) -> dtype
{ return lhs / value; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator/(const Matrix<dtype> &lhs, const std::complex<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](dtype value) -> std::complex<dtype>
{ return value / rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator/(const std::complex<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [lhs](dtype value) -> std::complex<dtype>
{ return lhs / value; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator/(const Matrix<std::complex<dtype>> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
{ return value / rhs; };
Matrix<std::complex<dtype>> 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 <typename dtype>
AIS_EXPORT Matrix<std::complex<dtype>> operator/(dtype lhs, const Matrix<std::complex<dtype>> &rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
const auto function = [lhs](std::complex<dtype> value) -> std::complex<dtype>
{ return lhs / value; };
Matrix<std::complex<dtype>> 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 <typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
AIS_EXPORT Matrix<dtype> &operator%=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Modulus the elements of two arrays
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
AIS_EXPORT Matrix<dtype> &operator%=(Matrix<dtype> &lhs, const Matrix<dtype> &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 <typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
AIS_EXPORT Matrix<dtype> &operator%=(Matrix<dtype> &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 <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
AIS_EXPORT Matrix<dtype> &operator%=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator%(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray %= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Modulus of the array and the scaler
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator%(const Matrix<dtype> &lhs, dtype rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray %= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Modulus of the scaler and the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
AIS_EXPORT Matrix<dtype> operator%(dtype lhs, const Matrix<dtype> &rhs)
{
Matrix<dtype> 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 <typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
AIS_EXPORT Matrix<dtype> operator%(dtype lhs, const Matrix<dtype> &rhs)
{
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator|=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Bitwise or the scaler to the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator|=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator|(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray |= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Takes the bitwise or of the array and the scaler
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator|(const Matrix<dtype> &lhs, dtype rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray |= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Takes the bitwise or of the sclar and the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator|(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs | lhs;
}
//============================================================================
// Method Description:
/// Bitwise and the elements of two arrays
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator&=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Bitwise and the scaler to the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator&=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator&(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray &= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Takes the bitwise and of the array and the scaler
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator&(const Matrix<dtype> &lhs, dtype rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray &= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Takes the bitwise and of the sclar and the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator&(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs & lhs;
}
//============================================================================
// Method Description:
/// Bitwise xor the elements of two arrays
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator^=(Matrix<dtype> &lhs, const Matrix<dtype> &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<dtype>());
return lhs;
}
//============================================================================
// Method Description:
/// Bitwise xor the scaler to the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator^=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator^(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray ^= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Takes the bitwise xor of the array and the scaler
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator^(const Matrix<dtype> &lhs, dtype rhs)
{
auto returnArray = Matrix<dtype>(lhs);
returnArray ^= rhs;
return returnArray;
}
//============================================================================
// Method Description:
/// Takes the bitwise xor of the sclar and the array
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator^(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs ^ lhs;
}
//============================================================================
// Method Description:
/// Takes the bitwise not of the array
///
/// @param inArray
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> operator~(const Matrix<dtype> &inArray)
{
STATIC_ASSERT_INTEGER(dtype);
const auto function = [](dtype value) -> dtype
{ return ~value; };
Matrix<dtype> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator&&(const Matrix<dtype> &lhs, const Matrix<dtype> &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<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator&&(const Matrix<dtype> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator&&(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs && lhs;
}
//============================================================================
// Method Description:
/// Takes the or of the elements of two arrays
///
/// @param lhs
/// @param rhs
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<bool> operator||(const Matrix<dtype> &lhs, const Matrix<dtype> &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<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator||(const Matrix<dtype> &lhs, dtype rhs)
{
STATIC_ASSERT_ARITHMETIC(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator||(dtype lhs, const Matrix<dtype> &rhs)
{
return rhs || lhs;
}
//============================================================================
// Method Description:
/// Takes the not of the array
///
/// @param inArray
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<bool> operator!(const Matrix<dtype> &inArray)
{
STATIC_ASSERT_ARITHMETIC(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator==(const Matrix<dtype> &lhs, const Matrix<dtype> &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<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator==(const Matrix<dtype> &lhs, dtype inValue)
{
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator==(dtype inValue, const Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<bool> operator!=(const Matrix<dtype> &lhs, const Matrix<dtype> &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<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator!=(const Matrix<dtype> &lhs, dtype inValue)
{
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator!=(dtype inValue, const Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<bool> operator<(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator<(const Matrix<dtype> &lhs, dtype inValue)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator<(dtype inValue, const Matrix<dtype> &inArray)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator>(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator>(const Matrix<dtype> &lhs, dtype inValue)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator>(dtype inValue, const Matrix<dtype> &inArray)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator<=(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator<=(const Matrix<dtype> &lhs, dtype inValue)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator<=(dtype inValue, const Matrix<dtype> &inArray)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator>=(const Matrix<dtype> &lhs, const Matrix<dtype> &rhs)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
if (lhs.shape() != rhs.shape())
{
THROW_INVALID_ARGUMENT("Array dimensions do not match.");
}
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator>=(const Matrix<dtype> &lhs, dtype inValue)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<bool> operator>=(dtype inValue, const Matrix<dtype> &inArray)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
Matrix<bool> 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 <typename dtype>
AIS_EXPORT Matrix<dtype> &operator<<=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator<<(const Matrix<dtype> &lhs, uint8_t inNumBits)
{
STATIC_ASSERT_INTEGER(dtype);
Matrix<dtype> returnArray(lhs);
returnArray <<= inNumBits;
return returnArray;
}
//============================================================================
// Method Description:
/// Bitshifts right the elements of the array
///
/// @param lhs
/// @param inNumBits
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator>>=(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator>>(const Matrix<dtype> &lhs, uint8_t inNumBits)
{
STATIC_ASSERT_INTEGER(dtype);
Matrix<dtype> returnArray(lhs);
returnArray >>= inNumBits;
return returnArray;
}
//============================================================================
// Method Description:
/// prefix incraments the elements of an array
///
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator++(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator++(Matrix<dtype> &lhs, int)
{
auto copy = Matrix<dtype>(lhs);
++lhs;
return copy;
}
//============================================================================
// Method Description:
/// prefix decrements the elements of an array
///
/// @return Matrix
///
template <typename dtype>
AIS_EXPORT Matrix<dtype> &operator--(Matrix<dtype> &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 <typename dtype>
AIS_EXPORT Matrix<dtype> operator--(Matrix<dtype> &lhs, int)
{
auto copy = Matrix<dtype>(lhs);
--lhs;
return copy;
}
//============================================================================
// Method Description:
/// io operator for the Matrix class
///
/// @param inOStream
/// @param inArray
/// @return std::ostream
///
template <typename dtype>
AIS_EXPORT std::ostream &operator<<(std::ostream &inOStream, const Matrix<dtype> &inArray)
{
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype);
inOStream << inArray.str();
return inOStream;
}
} // namespace ais