1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
//
// Created by Keuin on 2022/4/11.
//
#include <cmath>
static inline bool eq(int a, int b) {
return a == b;
}
static inline bool eq(long long a, long long b) {
return a == b;
}
static inline bool eq(double a, double b) {
// FIXME broken on large values
// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
// https://stackoverflow.com/a/253874/14332799
const double c = a - b;
return c <= 1e-14 && c >= -1e-14;
}
// 3-dim vector
template<typename T>
struct vec3 {
T x;
T y;
T z;
vec3 operator+(const vec3 &b) const {
return vec3{.x=x + b.x, .y=y + b.y, .z=z + b.z};
}
vec3 operator-() const {
return vec3{.x = -x, .y = -y, .z = -z};
}
vec3 operator-(const vec3 &b) const {
return *this + (-b);
}
bool operator==(const vec3 b) const {
return eq(x, b.x) && eq(y, b.y) && eq(z, b.z);
}
// dot product (aka inner product, or scalar product, producing a scalar)
T dot(const vec3 &b) const {
return x * b.x + y * b.y + z * b.z;
}
// cross product (aka outer product, or vector product, producing a vector)
vec3 cross(const vec3 &b) const {
return vec3{.x=y * b.z - z * b.y, .y=x * b.z - z * b.x, .z=x * b.y - y * b.x};
}
// norm value
double norm(const int level = 2) const {
if (level == 2) {
return std::abs(sqrt(x * x + y * y + z * z));
} else if (level == 1) {
return std::abs(x) + std::abs(y) + std::abs(z);
} else {
return powl(powl(x, level) + powl(y, level) + powl(z, level), 1.0 / level);
}
}
vec3 unit_vec() const {
return *this * (1.0 / norm());
}
};
// print to ostream
template<typename T>
std::ostream &operator<<(std::ostream &out, const vec3<T> &vec) {
return out << "vec3[x=" << vec.x << ", y=" << vec.y << ", z=" << vec.z << ']';
}
// product vec3 by a scalar
template<typename T, typename S>
vec3<T> operator*(const vec3<T> &vec, const S &b) {
return vec3<T>{.x=(T) (vec.x * b), .y=(T) (vec.y * b), .z=(T) (vec.z * b)};
}
// product vec3 by a scalar
template<typename T, typename S>
vec3<T> operator*(const S &b, const vec3<T> &vec) {
return vec3<T>{.x=(T) (vec.x * b), .y=(T) (vec.y * b), .z=(T) (vec.z * b)};
}
// product vec3 by the inversion of a scalar (div by a scalar)
template<typename T, typename S>
vec3<T> operator/(const vec3<T> &vec, const S &b) {
return vec3<T>{.x=(T) (vec.x / b), .y=(T) (vec.y / b), .z=(T) (vec.z / b)};
}
// scalar product (inner product)
template<typename T>
T dot(const vec3<T> &a, const vec3<T> &b) {
return a.dot(b);
}
// vector product (outer product)
template<typename T>
vec3<T> cross(const vec3<T> &a, const vec3<T> &b) {
return a.cross(b);
}
// 3-dim vector (int)
using vec3i = vec3<int>;
// 3-dim vector (long long)
using vec3l = vec3<long long>;
// 3-dim vector (float)
using vec3f = vec3<float>;
// 3-dim vector (double)
using vec3d = vec3<double>;
|