Element-wise operations: Difference between revisions
Content added Content deleted
SqrtNegInf (talk | contribs) 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}}== |