Element-wise operations: Difference between revisions

Content added Content deleted
m (→‎{{header|Raku}}: Fix comment: Perl 6 --> Raku)
(Added C++ solution)
Line 414: Line 414:
[ 75, 74, 73, 72 ]
[ 75, 74, 73, 72 ]
[ 61, 60, 59, 58 ]</pre>
[ 61, 60, 59, 58 ]</pre>

=={{header|C++}}==
<lang cpp>#include <cassert>
#include <cmath>
#include <iostream>
#include <valarray>

template <typename scalar_type> class matrix {
public:
matrix(size_t rows, size_t columns) : rows_(rows), columns_(columns) {
elements_.resize(rows * columns);
}
matrix(size_t rows, size_t columns, scalar_type value)
: rows_(rows), columns_(columns), elements_(value, rows * columns) {}

size_t rows() const { return rows_; }
size_t columns() const { return columns_; }

const scalar_type& at(size_t row, size_t column) const {
assert(row < rows_);
assert(column < columns_);
return elements_[index(row, column)];
}
scalar_type& at(size_t row, size_t column) {
assert(row < rows_);
assert(column < columns_);
return elements_[index(row, column)];
}

matrix& operator+=(scalar_type e) {
elements_ += e;
return *this;
}
matrix& operator-=(scalar_type e) {
elements_ -= e;
return *this;
}
matrix& operator*=(scalar_type e) {
elements_ *= e;
return *this;
}
matrix& operator/=(scalar_type e) {
elements_ /= e;
return *this;
}

matrix& operator+=(const matrix& other) {
assert(rows_ == other.rows_);
assert(columns_ == other.columns_);
elements_ += other.elements_;
return *this;
}
matrix& operator-=(const matrix& other) {
assert(rows_ == other.rows_);
assert(columns_ == other.columns_);
elements_ -= other.elements_;
return *this;
}
matrix& operator*=(const matrix& other) {
assert(rows_ == other.rows_);
assert(columns_ == other.columns_);
elements_ *= other.elements_;
return *this;
}
matrix& operator/=(const matrix& other) {
assert(rows_ == other.rows_);
assert(columns_ == other.columns_);
elements_ /= other.elements_;
return *this;
}

matrix& negate() {
for (scalar_type& element : elements_)
element = -element;
return *this;
}
matrix& invert() {
for (scalar_type& element : elements_)
element = 1 / element;
return *this;
}

friend matrix pow(const matrix& a, scalar_type b) {
return matrix(a.rows_, a.columns_, std::pow(a.elements_, b));
}
friend matrix pow(const matrix& a, const matrix& b) {
assert(a.rows_ == b.rows_);
assert(a.columns_ == b.columns_);
return matrix(a.rows_, a.columns_, std::pow(a.elements_, b.elements_));
}
private:
matrix(size_t rows, size_t columns, std::valarray<scalar_type>&& values)
: rows_(rows), columns_(columns), elements_(std::move(values)) {}

size_t index(size_t row, size_t column) const {
return row * columns_ + column;
}
size_t rows_;
size_t columns_;
std::valarray<scalar_type> elements_;
};

template <typename scalar_type>
matrix<scalar_type> operator+(const matrix<scalar_type>& a, scalar_type b) {
matrix<scalar_type> c(a);
c += b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator-(const matrix<scalar_type>& a, scalar_type b) {
matrix<scalar_type> c(a);
c -= b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator*(const matrix<scalar_type>& a, scalar_type b) {
matrix<scalar_type> c(a);
c *= b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator/(const matrix<scalar_type>& a, scalar_type b) {
matrix<scalar_type> c(a);
c /= b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator+(scalar_type a, const matrix<scalar_type>& b) {
matrix<scalar_type> c(b);
c += a;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator-(scalar_type a, const matrix<scalar_type>& b) {
matrix<scalar_type> c(b);
c.negate() += a;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator*(scalar_type a, const matrix<scalar_type>& b) {
matrix<scalar_type> c(b);
c *= a;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator/(scalar_type a, const matrix<scalar_type>& b) {
matrix<scalar_type> c(b);
c.invert() *= a;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator+(const matrix<scalar_type>& a,
const matrix<scalar_type>& b) {
matrix<scalar_type> c(a);
c += b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator-(const matrix<scalar_type>& a,
const matrix<scalar_type>& b) {
matrix<scalar_type> c(a);
c -= b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator*(const matrix<scalar_type>& a,
const matrix<scalar_type>& b) {
matrix<scalar_type> c(a);
c *= b;
return c;
}

template <typename scalar_type>
matrix<scalar_type> operator/(const matrix<scalar_type>& a,
const matrix<scalar_type>& b) {
matrix<scalar_type> c(a);
c /= b;
return c;
}

template <typename scalar_type>
void print(std::ostream& out, const matrix<scalar_type>& matrix) {
out << '[';
size_t rows = matrix.rows(), columns = matrix.columns();
for (size_t row = 0; row < rows; ++row) {
if (row > 0)
out << ", ";
out << '[';
for (size_t column = 0; column < columns; ++column) {
if (column > 0)
out << ", ";
out << matrix.at(row, column);
}
out << ']';
}
out << "]\n";
}

void test_matrix_matrix() {
const size_t rows = 3, columns = 2;
matrix<double> a(rows, columns);
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j)
a.at(i, j) = double(columns * i + j + 1);
}
matrix<double> b(a);

std::cout << "a + b:\n";
print(std::cout, a + b);

std::cout << "\na - b:\n";
print(std::cout, a - b);

std::cout << "\na * b:\n";
print(std::cout, a * b);

std::cout << "\na / b:\n";
print(std::cout, a / b);

std::cout << "\npow(a, b):\n";
print(std::cout, pow(a, b));
}

void test_matrix_scalar() {
const size_t rows = 3, columns = 4;
matrix<double> a(rows, columns);
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j)
a.at(i, j) = double(columns * i + j + 1);
}

std::cout << "a + 10:\n";
print(std::cout, a + 10.0);

std::cout << "\na - 10:\n";
print(std::cout, a - 10.0);

std::cout << "\n10 - a:\n";
print(std::cout, 10.0 - a);

std::cout << "\na * 10:\n";
print(std::cout, a * 10.0);

std::cout << "\na / 10:\n";
print(std::cout, a / 10.0);

std::cout << "\npow(a, 0.5):\n";
print(std::cout, pow(a, 0.5));
}

int main() {
test_matrix_matrix();
std::cout << '\n';
test_matrix_scalar();
return 0;
}</lang>

{{out}}
<pre>
a + b:
[[2, 4], [6, 8], [10, 12]]

a - b:
[[0, 0], [0, 0], [0, 0]]

a * b:
[[1, 4], [9, 16], [25, 36]]

a / b:
[[1, 1], [1, 1], [1, 1]]

pow(a, b):
[[1, 4], [27, 256], [3125, 46656]]

a + 10:
[[11, 12, 13, 14], [15, 16, 17, 18], [19, 20, 21, 22]]

a - 10:
[[-9, -8, -7, -6], [-5, -4, -3, -2], [-1, 0, 1, 2]]

10 - a:
[[9, 8, 7, 6], [5, 4, 3, 2], [1, 0, -1, -2]]

a * 10:
[[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120]]

a / 10:
[[0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8], [0.9, 1, 1.1, 1.2]]

pow(a, 0.5):
[[1, 1.41421, 1.73205, 2], [2.23607, 2.44949, 2.64575, 2.82843], [3, 3.16228, 3.31662, 3.4641]]
</pre>


=={{header|Clojure}}==
=={{header|Clojure}}==