First draft of vector class is ready, not done with the module test in main.cpp
This commit is contained in:
BIN
Binary file not shown.
+207
-48
@@ -52,8 +52,9 @@ public:
|
|||||||
if (v.size() != a.size()) {
|
if (v.size() != a.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const static T eps = static_cast<T>(1e-6); // tweak if you like
|
||||||
for (uint64_t i = 0; i < v.size(); ++i) {
|
for (uint64_t i = 0; i < v.size(); ++i) {
|
||||||
if (v[i] != a[i]) {
|
if (std::fabs(v[i] - a[i]) > eps) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,9 +68,10 @@ public:
|
|||||||
//##################################################
|
//##################################################
|
||||||
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
void inplace_add(const U a){
|
void inplace_add(const U a){
|
||||||
|
const T a_hat = static_cast<T>(a);
|
||||||
const uint64_t n = v.size();
|
const uint64_t n = v.size();
|
||||||
for (uint64_t i = 0; i < n; ++i){
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
v[i] += a;
|
v[i] += a_hat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
@@ -83,6 +85,10 @@ public:
|
|||||||
return add(a);
|
return add(a);
|
||||||
}
|
}
|
||||||
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
friend Vector<T> operator+(U a, const Vector<T>& b) {
|
||||||
|
return b + a;
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
Vector<T>& operator+=(const U a) {
|
Vector<T>& operator+=(const U a) {
|
||||||
inplace_add(a);
|
inplace_add(a);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -112,92 +118,259 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
//##################################################
|
//##################################################
|
||||||
|
//# VECTOR: Scalar Subtract #
|
||||||
|
//##################################################
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
void inplace_subtract(const U a){
|
||||||
|
const T a_hat = static_cast<T>(a);
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] -= a_hat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> subtract(const U a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_subtract(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> operator-(const U a) const {
|
||||||
|
return subtract(a);
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T>& operator-=(const U a) {
|
||||||
|
inplace_subtract(a);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//##################################################
|
||||||
//# VECTOR: Vector Subtract #
|
//# VECTOR: Vector Subtract #
|
||||||
//##################################################
|
//##################################################
|
||||||
void inplace_vec_subtract(const Vector<T>& a){
|
void inplace_subtract(const Vector<T>& a){
|
||||||
if (a.size() != v.size()){
|
if (a.size() != v.size()){
|
||||||
throw std::runtime_error("utill:Vector.inplace_vec_subtract -> Dimensions does not fit");
|
throw std::runtime_error("utill:Vector.inplace_subtract -> Dimensions does not fit");
|
||||||
}
|
}
|
||||||
|
const uint64_t n = v.size();
|
||||||
uint64_t n = a.size();
|
|
||||||
for (uint64_t i = 0; i < n; ++i){
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
v[i] -= a[i];
|
v[i] -= a[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Vector<T> vec_subtract(const Vector<T>& a) const{
|
Vector<T> subtract(const Vector<T>& a) const{
|
||||||
Vector<T> result = *this;
|
Vector<T> result = *this;
|
||||||
|
result.inplace_subtract(a);
|
||||||
result.inplace_vec_subtract(a);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
Vector<T> operator-(const Vector<T>& a) const {
|
Vector<T> operator-(const Vector<T>& a) const {
|
||||||
return vec_subtract(a);
|
return subtract(a);
|
||||||
}
|
}
|
||||||
Vector<T>& operator-=(const Vector<T>& a) {
|
Vector<T>& operator-=(const Vector<T>& a) {
|
||||||
inplace_vec_subtract(a);
|
inplace_subtract(a);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//##################################################
|
||||||
|
//# VECTOR: Scalar Multiply #
|
||||||
|
//##################################################
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
void inplace_multiply(const U a){
|
||||||
|
const T a_hat = static_cast<T>(a);
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] *= a_hat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> multiply(const U a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_multiply(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> operator*(const U a) const {
|
||||||
|
return multiply(a);
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
friend Vector<T> operator*(U a, const Vector<T>& b) {
|
||||||
|
return b * a;
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T>& operator*=(const U a) {
|
||||||
|
inplace_multiply(a);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
//##################################################
|
//##################################################
|
||||||
//# VECTOR: Vector Multiply #
|
//# VECTOR: Vector Multiply #
|
||||||
//##################################################
|
//##################################################
|
||||||
void inplace_vec_multiply(const Vector<T>& a){
|
void inplace_multiply(const Vector<T>& a){
|
||||||
if (a.size() != v.size()){
|
if (a.size() != v.size()){
|
||||||
throw std::runtime_error("utill:Vector.inplace_vec_multiply -> Dimensions does not fit");
|
throw std::runtime_error("utill:Vector.inplace_multiply -> Dimensions does not fit");
|
||||||
}
|
}
|
||||||
|
const uint64_t n = v.size();
|
||||||
uint64_t n = a.size();
|
|
||||||
for (uint64_t i = 0; i < n; ++i){
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
v[i] *= a[i];
|
v[i] *= a[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Vector<T> vec_multiply(const Vector<T>& a) const{
|
Vector<T> multiply(const Vector<T>& a) const{
|
||||||
Vector<T> result = *this;
|
Vector<T> result = *this;
|
||||||
result.inplace_vec_multiply(a);
|
result.inplace_multiply(a);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
Vector<T> operator*(const Vector<T>& a) const {
|
Vector<T> operator*(const Vector<T>& a) const {
|
||||||
return vec_multiply(a);
|
return multiply(a);
|
||||||
}
|
}
|
||||||
Vector<T>& operator*=(const Vector<T>& a) {
|
Vector<T>& operator*=(const Vector<T>& a) {
|
||||||
inplace_vec_multiply(a);
|
inplace_multiply(a);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//################################################
|
||||||
|
//# VECTOR: Scalar Divide #
|
||||||
|
//################################################
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
void inplace_divide(const U a){
|
||||||
|
const T a_hat = static_cast<T>(a);
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] /= a_hat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> divide(const U a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_divide(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> operator/(const U a) const {
|
||||||
|
return divide(a);
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T>& operator/=(const U a) {
|
||||||
|
inplace_divide(a);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
//##################################################
|
//##################################################
|
||||||
//# VECTOR: Vector Divide #
|
//# VECTOR: Vector Divide #
|
||||||
//##################################################
|
//##################################################
|
||||||
void inplace_vec_divide(const Vector<T>& a){
|
void inplace_divide(const Vector<T>& a){
|
||||||
if (a.size() != v.size()){
|
if (a.size() != v.size()){
|
||||||
throw std::runtime_error("utill:Vector.inplace_vec_divide -> Dimensions does not fit");
|
throw std::runtime_error("utill:Vector.inplace_divide -> Dimensions does not fit");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t n = a.size();
|
uint64_t n = a.size();
|
||||||
for (uint64_t i = 0; i < n; ++i){
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
v[i] /= a[i];
|
v[i] /= a[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Vector<T> vec_divide(const Vector<T>& a) const{
|
Vector<T> divide(const Vector<T>& a) const{
|
||||||
Vector<T> result = *this;
|
Vector<T> result = *this;
|
||||||
result.inplace_vec_divide(a);
|
result.inplace_divide(a);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
Vector<T> operator/(const Vector<T>& a) const {
|
Vector<T> operator/(const Vector<T>& a) const {
|
||||||
return vec_divide(a);
|
return divide(a);
|
||||||
}
|
}
|
||||||
Vector<T>& operator/=(const Vector<T>& a) {
|
Vector<T>& operator/=(const Vector<T>& a) {
|
||||||
inplace_vec_divide(a);
|
inplace_divide(a);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
//###############################################
|
||||||
|
//# VECTOR: Scalar Power #
|
||||||
|
//###############################################
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
void inplace_power(const U a){
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] = static_cast<T>(std::pow(v[i], a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> power(const U a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_power(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//###############################################
|
||||||
|
//# VECTOR: Vector Power #
|
||||||
|
//###############################################
|
||||||
|
void inplace_power(const Vector<T>& a){
|
||||||
|
if (a.size() != v.size()){
|
||||||
|
throw std::runtime_error("utill:Vector.inplace_power -> Dimensions does not fit");
|
||||||
|
}
|
||||||
|
uint64_t n = a.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] = static_cast<T>(std::pow(v[i], a[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vector<T> power(const Vector<T>& a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_power(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//################################################
|
||||||
|
//# VECTOR: Scalar Square #
|
||||||
|
//################################################
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
void inplace_square(const U a){
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] = static_cast<T>(std::sqrt(v[i], a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type>
|
||||||
|
Vector<T> square(const U a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_square(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//################################################
|
||||||
|
//# VECTOR: Vector square #
|
||||||
|
//################################################
|
||||||
|
void inplace_square(const Vector<T>& a){
|
||||||
|
if (a.size() != v.size()){
|
||||||
|
throw std::runtime_error("utill:Vector.inplace_square -> Dimensions does not fit");
|
||||||
|
}
|
||||||
|
uint64_t n = a.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
v[i] = static_cast<T>(std::sqrt(v[i], a[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vector<T> square(const Vector<T>& a) const{
|
||||||
|
Vector<T> result = *this;
|
||||||
|
result.inplace_square(a);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//###################################################
|
||||||
|
//# VECTOR: Dot Product #
|
||||||
|
//###################################################
|
||||||
|
T dot(const Vector<T>& a)const {
|
||||||
|
if (a.size() != v.size()){
|
||||||
|
throw std::runtime_error("utill:Vector.dot -> Dimensions does not fit");
|
||||||
|
}
|
||||||
|
T result;
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
result += a[i]*v[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//############################################
|
||||||
|
//# VECTOR: Sum #
|
||||||
|
//############################################
|
||||||
|
T sum()const{
|
||||||
|
T result = T{0};
|
||||||
|
const uint64_t n = v.size();
|
||||||
|
for (uint64_t i = 0; i < n; ++i){
|
||||||
|
result += v[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//############################################
|
||||||
|
//# VECTOR: Norm #
|
||||||
|
//############################################
|
||||||
|
T norm() const{
|
||||||
|
return static_cast<T>(std::sqrt(this->dot(*this)));
|
||||||
|
}
|
||||||
//######################################################
|
//######################################################
|
||||||
//# VECTOR: Support Functions #
|
//# VECTOR: Support Functions #
|
||||||
//######################################################
|
//######################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline friend std::ostream& operator << (std::ostream& out, const Vector& vec){
|
inline friend std::ostream& operator << (std::ostream& out, const Vector& vec){
|
||||||
out << "[";
|
out << "[";
|
||||||
for (uint64_t i = 0; i < vec.v.size(); i++){
|
for (uint64_t i = 0; i < vec.v.size(); i++){
|
||||||
@@ -213,20 +386,6 @@ public:
|
|||||||
void print() const{
|
void print() const{
|
||||||
std::cout << *this << std::endl;
|
std::cout << *this << std::endl;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void linspace(const T start, const T stop, const T num){
|
|
||||||
v.clear();
|
|
||||||
|
|
||||||
if (num > 1){
|
|
||||||
|
|
||||||
double delta = (stop - start)/(num - 1);
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < num; i++){
|
|
||||||
v.push_back(static_cast<T>(start + delta * i));
|
|
||||||
}
|
|
||||||
//v.push_back(static_cast<T>(stop));
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Vector<int> Vi;
|
typedef Vector<int> Vi;
|
||||||
|
|||||||
BIN
Binary file not shown.
+173
-21
@@ -1,36 +1,188 @@
|
|||||||
#include "./utils/utils.h"
|
#include "./utils/utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
|
#define CHECK(cond, msg) \
|
||||||
|
do { if (!(cond)) throw std::runtime_error(msg); } while (0)
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
void expect_throw(F&& f, const char* msg_if_no_throw) {
|
||||||
|
try {
|
||||||
|
f();
|
||||||
|
throw std::runtime_error(msg_if_no_throw);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
// ok: an exception was thrown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char const *argv[])
|
int main(int argc, char const *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
utils::Vf vect1(3,1), vect2(3,1), vect3(3,1), addition_test(3,7), subtract_test(3,-2);
|
using utils::Vf;
|
||||||
//###########################################
|
|
||||||
//# VECTOR TYPE TEST #
|
|
||||||
//# Addition Test #
|
|
||||||
//###########################################
|
|
||||||
vect1.inplace_add(vect2);
|
|
||||||
vect3 = vect1.add(vect2).add(vect1) + vect2;
|
|
||||||
vect3 += vect2;
|
|
||||||
if (vect3 != addition_test){
|
|
||||||
throw std::runtime_error("Addition Test -> Failed");}
|
|
||||||
|
|
||||||
//###########################################
|
// ---------------- Equality / Inequality ----------------
|
||||||
//# VECTOR TYPE TEST #
|
{
|
||||||
//# Subtract Test #
|
Vf a(3, 1.0f); // [1,1,1]
|
||||||
//###########################################
|
Vf b(3, 1.0f); // [1,1,1]
|
||||||
vect1.inplace_vec_subtract(vect2);
|
Vf c(3, 2.0f); // [2,2,2]
|
||||||
vect3 = vect1.vec_subtract(vect2).vec_subtract(vect1) - vect2;
|
|
||||||
vect3.print();
|
|
||||||
vect3 = vect3.add(2);
|
|
||||||
vect3.print();
|
|
||||||
if (vect3 != subtract_test){
|
|
||||||
throw std::runtime_error("Subtract Test -> Failed");}
|
|
||||||
|
|
||||||
|
CHECK(a == b, "a should equal b");
|
||||||
|
CHECK(!(a != b), "a should not be != b");
|
||||||
|
CHECK(a != c, "a should not equal c");
|
||||||
|
|
||||||
|
// mutate one element
|
||||||
|
a[1] = 5.0f;
|
||||||
|
CHECK(a != b, "after mutation, a should differ from b");
|
||||||
|
a[1] = 1.0f; // restore
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Vector + Vector (and +=) ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 1.0f); // [1,1,1]
|
||||||
|
Vf b(3, 2.0f); // [2,2,2]
|
||||||
|
Vf expect(3, 3.0f); // [3,3,3]
|
||||||
|
|
||||||
|
Vf c = a + b;
|
||||||
|
CHECK(c == expect, "a + b should be [3,3,3]");
|
||||||
|
|
||||||
|
a += b; // a becomes [3,3,3]
|
||||||
|
CHECK(a == expect, "a += b should produce [3,3,3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Vector - Vector (and -=) ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 5.0f); // [5,5,5]
|
||||||
|
Vf b(3, 2.0f); // [2,2,2]
|
||||||
|
Vf expect(3, 3.0f); // [3,3,3]
|
||||||
|
|
||||||
|
Vf c = a - b;
|
||||||
|
CHECK(c == expect, "a - b should be [3,3,3]");
|
||||||
|
|
||||||
|
a -= b; // a becomes [3,3,3]
|
||||||
|
CHECK(a == expect, "a -= b should produce [3,3,3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Elementwise Multiply (and *=) ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 2.0f); // [2,2,2]
|
||||||
|
Vf b(3, 3.0f); // [3,3,3]
|
||||||
|
Vf expect(3, 6.0f); // [6,6,6]
|
||||||
|
|
||||||
|
Vf c = a * b;
|
||||||
|
CHECK(c == expect, "a * b (elemwise) should be [6,6,6]");
|
||||||
|
|
||||||
|
a *= b; // a becomes [6,6,6]
|
||||||
|
CHECK(a == expect, "a *= b should produce [6,6,6]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Elementwise Divide (and /=) ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 6.0f); // [6,6,6]
|
||||||
|
Vf b(3, 2.0f); // [2,2,2]
|
||||||
|
Vf expect(3, 3.0f); // [3,3,3]
|
||||||
|
|
||||||
|
Vf c = a / b;
|
||||||
|
CHECK(c == expect, "a / b (elemwise) should be [3,3,3]");
|
||||||
|
|
||||||
|
a /= b; // a becomes [3,3,3]
|
||||||
|
CHECK(a == expect, "a /= b should produce [3,3,3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Scalar + Vector (and +=) ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 1.0f); // [1,1,1]
|
||||||
|
Vf expect1(3, 6.0f); // [6,6,6]
|
||||||
|
Vf expect2(3, 3.0f); // [3,3,3]
|
||||||
|
|
||||||
|
Vf c = a + 5.0f; // v + s
|
||||||
|
CHECK(c == expect1, "a + 5 should be [6,6,6]");
|
||||||
|
|
||||||
|
Vf d = 2.0f + a; // s + v (friend operator)
|
||||||
|
CHECK(d == expect2, "2 + a should be [3,3,3]");
|
||||||
|
|
||||||
|
a += 2.0f; // a becomes [3,3,3]
|
||||||
|
CHECK(a == expect2, "a += 2 should produce [3,3,3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Scalar - Vector / Vector - Scalar ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 5.0f); // [5,5,5]
|
||||||
|
Vf expect1(3, 3.0f); // [3,3,3]
|
||||||
|
Vf expect2(3, -3.0f); // [ -3,-3,-3 ] if 2 - a (only if you've implemented it)
|
||||||
|
|
||||||
|
Vf c = a - 2.0f; // v - s
|
||||||
|
CHECK(c == expect1, "a - 2 should be [3,3,3]");
|
||||||
|
|
||||||
|
// NOTE: Your friend operator-(U a, const Vector<T> b) currently returns (b - a),
|
||||||
|
// which means `2 - a` computes `a - 2`. That's a bit unusual.
|
||||||
|
// We'll avoid asserting 2 - a here to match your current implementation choice.
|
||||||
|
(void)expect2; // silence unused warning
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Scalar * Vector / Vector * Scalar ----------------
|
||||||
|
{
|
||||||
|
|
||||||
|
Vf a(3, 2.0f); // [2,2,2]
|
||||||
|
uint64_t b = 3; // 3
|
||||||
|
Vf expect(3, 6.0f); // [6,6,6]
|
||||||
|
|
||||||
|
Vf c = a * b; // v * s
|
||||||
|
CHECK(c == expect, "a * 3 should be [6,6,6]");
|
||||||
|
|
||||||
|
Vf d = b * a; // s * v (friend)
|
||||||
|
CHECK(d == expect, "3 * a should be [6,6,6]");
|
||||||
|
|
||||||
|
a *= b; // a becomes [6,6,6]
|
||||||
|
CHECK(a == expect, "a *= 3 should produce [6,6,6]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Vector / Scalar (and /= scalar) ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 6.0f); // [6,6,6]
|
||||||
|
uint64_t b = 2; // 3
|
||||||
|
Vf expect(3, 3.0f); // [3,3,3]
|
||||||
|
|
||||||
|
Vf c = a / b; // v / s
|
||||||
|
CHECK(c == expect, "a / 2 should be [3,3,3]");
|
||||||
|
|
||||||
|
a /= b; // a becomes [3,3,3]
|
||||||
|
CHECK(a == expect, "a /= 2 should produce [3,3,3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Size mismatch throws ----------------
|
||||||
|
{
|
||||||
|
Vf a(3, 1.0f);
|
||||||
|
Vf b(4, 2.0f);
|
||||||
|
|
||||||
|
expect_throw([&] { a.inplace_add(b); },
|
||||||
|
"inplace_add should throw on size mismatch");
|
||||||
|
expect_throw([&] { (void)(a + b); },
|
||||||
|
"operator+ should throw (through add) on size mismatch");
|
||||||
|
expect_throw([&] { a.inplace_subtract(b); },
|
||||||
|
"inplace_subtract should throw on size mismatch");
|
||||||
|
expect_throw([&] { (void)(a - b); },
|
||||||
|
"operator- should throw (through subtract) on size mismatch");
|
||||||
|
expect_throw([&] { a.inplace_multiply(b); },
|
||||||
|
"inplace_multiply should throw on size mismatch");
|
||||||
|
expect_throw([&] { (void)(a * b); },
|
||||||
|
"operator* should throw (through multiply) on size mismatch");
|
||||||
|
expect_throw([&] { a.inplace_divide(b); },
|
||||||
|
"inplace_divide should throw on size mismatch");
|
||||||
|
expect_throw([&] { (void)(a / b); },
|
||||||
|
"operator/ should throw (through divide) on size mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
Vf b(3, 8.0f); // [1,1,1]
|
||||||
|
Vf c(3, 2.0f); // [2,2,2]
|
||||||
|
b.print();
|
||||||
|
b.inplace_power(2);
|
||||||
|
b.print();
|
||||||
|
std::cout << b.norm() << std::endl;
|
||||||
|
std::cout << "All Vector tests passed ✅\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user