~rycwo/forge

forge/include/forge/vector.h.in -rw-r--r-- 5.8 KiB
e5de0236Ryan Chan Add support for basic line rendering 4 months ago
                                                                                
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// This file is part of Forge, the foundation library for Forge tools.
//
// Copyright (C) 2021 Ryan Chan <rycwo@posteo.net>
// SPDX-License-Identifier: GPL-3.0-only
//
// This Source Code Form is subject to the terms of the GNU General Public
// License v3.0 only. You should have received a copy of the license along with
// this program. If not, see <https://www.gnu.org/licenses/>.

// This file has sections that have been auto-generated by tmplgen. Edits should
// be made in the corresponding .h.in template file. Re-run Meson to generate a
// new version of this file.

#ifndef FORGE_VECTOR_H
#define FORGE_VECTOR_H

#include <math.h>

#include "forge/type.h"

{{$elementNames := list "x" "y" "z" "w" -}}
{{- range $n := list 2 3 4 -}}
{{- $elements := slice $elementNames 0 $n -}}

/*
 * Set vector elements to the given values.
 */
static inline void
fg_vec{{$n}}_set(fg_vec{{$n}} out{{range $i, $comp := $elements}}, fg_real {{$comp}}{{end}}) {
	{{- range $i, $comp := $elements}}
	out[{{$i}}] = {{$comp}};
	{{- end}}
}

/*
 * Set vector elements to zero.
 */
static inline void
fg_vec{{$n}}_zero(fg_vec{{$n}} out) {
	{{- range $i := until $n}}
	out[{{$i}}] = (fg_real)0.0;
	{{- end}}
}

/*
 * Copy vector elements.
 */
static inline void
fg_vec{{$n}}_copy(fg_vec{{$n}} out, fg_vec{{$n}} const a) {
	{{- range $i := until $n}}
	out[{{$i}}] = a[{{$i}}];
	{{- end}}
}

/*
 * Add two vectors, \\(\mathbf{out} = \mathbf{a} + \mathbf{b}\\).
 */
static inline void
fg_vec{{$n}}_add(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	{{- range $i := until $n}}
	out[{{$i}}] = a[{{$i}}] + b[{{$i}}];
	{{- end}}
}

/*
 * Subtract two vectors, \\(\mathbf{out} = \mathbf{a} - \mathbf{b}\\).
 */
static inline void
fg_vec{{$n}}_sub(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	{{- range $i := until $n}}
	out[{{$i}}] = a[{{$i}}] - b[{{$i}}];
	{{- end}}
}

/*
 * Multiply two vectors element-wise.
 *
 * Fun fact: this is less commonly referred to as the [Hadamard
 * product][hadamard], \\(\mathbf{out} = \mathbf{a} \odot \mathbf{b}\\).
 *
 * [hadamard]: https://en.wikipedia.org/wiki/Hadamard_product_(matrices)
 */
static inline void
fg_vec{{$n}}_mul(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	{{- range $i := until $n}}
	out[{{$i}}] = a[{{$i}}] * b[{{$i}}];
	{{- end}}
}

/*
 * Divide two vectors element-wise.
 *
 * Fun fact: this is less commonly referred to as [Hadamard division][hadamard],
 * \\(\mathbf{out} = \mathbf{a} \oslash \mathbf{b}\\).
 *
 * [hadamard]: https://en.wikipedia.org/wiki/Hadamard_product_(matrices)#Analogous_operations
 */
static inline void
fg_vec{{$n}}_div(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	{{- range $i := until $n}}
	out[{{$i}}] = a[{{$i}}] / b[{{$i}}];
	{{- end}}
}

/*
 * Take the element-wise minimum of two vectors,
 * \\(\mathbf{out}_i = min(\mathbf{a}_i, \mathbf{b}_i)\\).
 */
static inline void
fg_vec{{$n}}_min(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	{{- range $i := until $n}}
	out[{{$i}}] = (a[{{$i}}] < b[{{$i}}]) ? a[{{$i}}] : b[{{$i}}];
	{{- end}}
}

/*
 * Take the element-wise maximum of two vectors,
 * \\(\mathbf{out}_i = max(\mathbf{a}_i, \mathbf{b}_i)\\).
 */
static inline void
fg_vec{{$n}}_max(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	{{- range $i := until $n}}
	out[{{$i}}] = (a[{{$i}}] > b[{{$i}}]) ? a[{{$i}}] : b[{{$i}}];
	{{- end}}
}

/*
 * Multiply vector by scalar, \\(\mathbf{out} = \alpha\mathbf{a}\\).
 */
static inline void
fg_vec{{$n}}_scale(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_real alpha) {
	{{- range $i := until $n}}
	out[{{$i}}] = alpha * a[{{$i}}];
	{{- end}}
}

/*
 * Compute the [dot product](https://en.wikipedia.org/wiki/Dot_product) of two
 * vectors, \\(\alpha = \mathbf{a} \cdot \mathbf{b}\\).
 *
 * This may also be expressed as
 * \\(\alpha = \mathbf{a}^{\mathsf{T}}\mathbf{b}\\).
 */
static inline fg_real
fg_vec{{$n}}_dot(fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	return a[0] * b[0]{{range $i := slice (until $n) 1}} + a[{{$i}}] * b[{{$i}}]{{end}};
}

/*
 * Compute the [2-norm](https://en.wikipedia.org/wiki/Euclidean_distance) of the
 * given vector, \\(\alpha = \|\mathbf{a}\|_2\\).
 *
 * In some implementations this is referred to as the Euclidean norm or less
 * formally as the vector length.
 */
static inline fg_real
fg_vec{{$n}}_2norm(fg_vec{{$n}} const a) {
	return sqrt(a[0] * a[0]{{range $i := slice (until $n) 1}} + a[{{$i}}] * a[{{$i}}]{{end}});
}

/*
 * Compute the normalized vector of `a`,
 * \\(\mathbf{out} = \frac{\mathbf{a}}{\|\mathbf{a}\|_2}\\)
 *
 * A unit vector may also be referred to with a "hat" symbol (e.g.
 * \\(\mathbf{\hat{a}}\\)) in the documentation.
 *
 * `a` must be nonzero or will raise a floating-point exception (division by
 * zero).
 */
static inline void
fg_vec{{$n}}_unit(fg_vec{{$n}} out, fg_vec{{$n}} const a) {
	fg_vec{{$n}}_scale(out, a, (fg_real)1.0 / fg_vec{{$n}}_2norm(a));
}

/*
 * Compute the [projection][] of `a` on `b`,
 * \\(\mathbf{out} = (\mathbf{a} \cdot \mathbf{\hat{b}})\mathbf{\hat{b}}\\).
 *
 * `b` must be nonzero or will raise a floating-point exception (division by
 * zero).
 *
 * [projection]: https://en.wikipedia.org/wiki/Vector_projection
 */
static inline void
fg_vec{{$n}}_project(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	fg_vec{{$n}} tmp;
	fg_vec{{$n}}_unit(tmp, b);
	fg_vec{{$n}}_scale(out, tmp, fg_vec{{$n}}_dot(a, tmp));
}

/*
 * Compute the [rejection][] of `a` on `b`,
 * \\(\mathbf{out} = \mathbf{a} - (\mathbf{a} \cdot \mathbf{\hat{b}})\mathbf{\hat{b}}\\).
 *
 * `b` must be nonzero or will raise a floating-point exception (division by
 * zero).
 *
 * [rejection]: https://en.wikipedia.org/wiki/Vector_projection
 */
static inline void
fg_vec{{$n}}_reject(fg_vec{{$n}} out, fg_vec{{$n}} const a, fg_vec{{$n}} const b) {
	fg_vec{{$n}} tmp;
	fg_vec{{$n}}_project(tmp, a, b);
	fg_vec{{$n}}_sub(out, a, tmp);
}

{{end -}}

#endif // FORGE_VECTOR_H