#pragma once
#include <cmath>
#include <iostream>

struct Vector3f {
        float x;
        float y;
        float z;
};

Vector3f operator+(const Vector3f& a, const Vector3f& b) {
        Vector3f result = {a.x + b.x, a.y + b.y, a.z + b.z};
        return result;
}

Vector3f operator-(const Vector3f& a, const Vector3f& b) {
        Vector3f result = {a.x - b.x, a.y - b.y, a.z - b.z};
        return result;
}

Vector3f operator*(const Vector3f& a, float f) {
    Vector3f result = {f * a.x, f * a.y, f * a.z};
    return result;
}

Vector3f operator*(float f, const Vector3f& a) {
    Vector3f result = {f * a.x, f * a.y, f * a.z};
    return result;
}

int operator*(const Vector3f& a, const Vector3f& b) {
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

Vector3f operator/(const Vector3f& a, float f) {
        Vector3f result = {a.x / f, a.y / f, a.z / f};
        return result;
}

Vector3f operator+(const Vector3f& a) {
    return a;
}

Vector3f operator-(const Vector3f& a) {
    Vector3f result = {-a.x, -a.y, -a.z};
    return result;
}

bool operator==(const Vector3f& a, const Vector3f& b) {
    if (a.x == b.x && a.y == b.y && a.z == b.z) {
        return true;
    }
    return false;
}

bool operator!=(const Vector3f& a, const Vector3f& b) {
    return not (a == b);
}

void operator+=(Vector3f& a, const Vector3f& b) {
    a = a + b;
}

void operator-=(Vector3f& a, const Vector3f& b) {
    a = a - b;
}

void operator*=(Vector3f& a, float f) {
    a = f * a;
}

void operator/=(Vector3f& a, float f) {
    a = a / f;
}

float squared_norm(const Vector3f& a) {
    return a * a;
}

float norm(const Vector3f& a) {
    return sqrt(squared_norm(a));
}

void normalize(Vector3f& a) {
    a /= norm(a);
}

std::istream& operator>>(std::istream& in, Vector3f& a) {
    in >> a.x >> a.y >> a.z;
    return in;
}

std::ostream& operator<<(std::ostream& out, const Vector3f& a) {
        out << "(" << a.x << ", " << a.y << ", " << a.z << ")";
        return out;
}
