# source:libcfa/src/vec/vec2.hfa@1dd929e

Last change on this file since 1dd929e was 1dd929e, checked in by Dmitry Kobets <dkobets@…>, 4 years ago

Apply traits to each individual function of vector

Previously, vector had a single trait applied to all methods. However,
it was discovered that different types (i.e., int vs float) supported different
operations (int does not support the length operation)

• Property mode set to `100644`
File size: 5.5 KB
Line
1#pragma once
2#include <math.hfa>
3#include <iostream.hfa>
4
5trait zeroassn(otype T) {
6    T ?=?(T&, zero_t);
7};
8trait fromint(otype T) {
9    void ?{}(T&, int);
10};
11trait zero_assign(otype T) {
12    T ?=?(T&, zero_t);
13};
14trait subtract(otype T) {
15    T ?-?(T, T);
16    T -?(T);
17};
18trait add(otype T) {
19    T ?+?(T, T);
20};
21trait multiply(otype T) {
22    T ?*?(T, T);
23};
24trait divide(otype T) {
25    T ?/?(T, T);
26};
27trait lessthan(otype T) {
28    int ?<?(T, T);
29};
30trait equality(otype T) {
31    int ?==?(T, T);
32};
33trait sqrt(otype T) {
34    T sqrt(T);
35};
36
37static inline {
38// int
39int ?=?(int& n, zero_t) { return n = 0.f; }
40int sqrt(int a) { return sqrt((float)a); }
41/* float */
42void ?{}(float& a, int b) { a = b; }
43float ?=?(float& n, zero_t) { return n = 0.f; }
44/* double */
45void ?{}(double& a, int b) { a = b; }
46double ?=?(double& n, zero_t) { return n = 0L; }
47// long double
48void ?{}(long double& a, int b) { a = b; }
49long double ?=?(long double& n, zero_t) { return n = 0L; }
50}
51
52forall(otype T) {
53    struct vec2 {
54        T x, y;
55    };
56}
57
58forall(otype T) {
59    static inline {
60
61    // Constructors
62
63    void ?{}(vec2(T)& v, T x, T y) {
64        v.[x, y] = [x, y];
65    }
66
67    forall(| zero_assign(T))
68    void ?{}(vec2(T)& vec, zero_t) with (vec) {
69        x = y = 0;
70    }
71
72    void ?{}(vec2(T)& vec, T val) with (vec) {
73        x = y = val;
74    }
75
76    void ?{}(vec2(T)& vec, vec2(T) other) with (vec) {
77        [x,y] = other.[x,y];
78    }
79
80    // Assignment
81    void ?=?(vec2(T)& vec, vec2(T) other) with (vec) {
82        [x,y] = other.[x,y];
83    }
84    forall(| zero_assign(T))
85    void ?=?(vec2(T)& vec, zero_t) with (vec) {
86        x = y = 0;
87    }
88
89    // Primitive mathematical operations
90
91    // Subtraction
92
93    forall(| subtract(T)) {
94    vec2(T) ?-?(vec2(T) u, vec2(T) v) { // TODO( can't make this const ref )
95        return [u.x - v.x, u.y - v.y];
96    }
97    vec2(T)& ?-=?(vec2(T)& u, vec2(T) v) {
98        u = u - v;
99        return u;
100    }
101    vec2(T) -?(vec2(T)& v) with (v) {
102        return [-x, -y];
103    }
104    }
105
107    forall(| add(T)) {
108    vec2(T) ?+?(vec2(T) u, vec2(T) v) { // TODO( can't make this const ref )
109        return [u.x + v.x, u.y + v.y];
110    }
111    vec2(T)& ?+=?(vec2(T)& u, vec2(T) v) {
112        u = u + v;
113        return u;
114    }
115    }
116
117    // Scalar Multiplication
118    forall(| multiply(T)) {
119    vec2(T) ?*?(vec2(T) v, T scalar) with (v) { // TODO (can't make this const ref)
120        return [x * scalar, y * scalar];
121    }
122    vec2(T) ?*?(T scalar, vec2(T) v) { // TODO (can't make this const ref)
123        return v * scalar;
124    }
125    vec2(T)& ?*=?(vec2(T)& v, T scalar) {
126        v = v * scalar;
127        return v;
128    }
129    }
130
131    // Scalar Division
132    forall(| divide(T)) {
133    vec2(T) ?/?(vec2(T) v, T scalar) with (v) {
134        return [x / scalar, y / scalar];
135    }
136    vec2(T)& ?/=?(vec2(T)& v, T scalar) with (v) {
137        v = v / scalar;
138        return v;
139    }
140    }
141
142    // Relational Operators
143    forall(| equality(T)) {
144    bool ?==?(vec2(T) u, vec2(T) v) with (u) {
145        return x == v.x && y == v.y;
146    }
147    bool ?!=?(vec2(T) u, vec2(T) v) {
148        return !(u == v);
149    }
150    }
151
152    forall(| add(T) | multiply(T))
153    T dot(vec2(T) u, vec2(T) v) {
154        return u.x * v.x + u.y * v.y;
155    }
156
157    forall(| sqrt(T) | add(T) | multiply(T))
158    T length(vec2(T) v) {
159       return sqrt(dot(v, v));
160    }
161
162    forall(| add(T) | multiply(T))
163    T length_squared(vec2(T) v) {
164       return dot(v, v);
165    }
166
167    forall(| subtract(T) | sqrt(T) | add(T) | multiply(T))
168    T distance(vec2(T) v1, vec2(T) v2) {
169        return length(v1 - v2);
170    }
171
172    forall(| sqrt(T) | divide(T) | add(T) | multiply(T))
173    vec2(T) normalize(vec2(T) v) {
174        return v / sqrt(dot(v, v));
175    }
176
177    // Project vector u onto vector v
178    forall(| sqrt(T) | divide(T) | add(T) | multiply(T))
179    vec2(T) project(vec2(T) u, vec2(T) v) {
180        vec2(T) v_norm = normalize(v);
181        return v_norm * dot(u, v_norm);
182    }
183
184    // Reflect incident vector v with respect to surface with normal n
185    forall(| sqrt(T) | divide(T) | add(T) | multiply(T) | subtract(T) | fromint(T))
186    vec2(T) reflect(vec2(T) v, vec2(T) n) {
187        return v - (T){2} * project(v, n);
188    }
189
190    // Refract incident vector v with respect to surface with normal n
191    // eta is the ratio of indices of refraction between starting material and
192    // entering material (i.e., from air to water, eta = 1/1.33)
193    // v and n must already be normalized
194    forall(| sqrt(T) | add(T) | multiply(T) | subtract(T) | fromint(T) | lessthan(T) | zeroassn(T))
195    vec2(T) refract(vec2(T) v, vec2(T) n, T eta) {
196        T dotValue = dot(n, v);
197        T k = (T){1} - eta * eta * ((T){1} - dotValue * dotValue);
198        if (k < (T){0}) {
199            return 0;
200        }
201        return eta * v - (eta * dotValue + sqrt(k)) * n;
202    }
203
204    // Given a perturbed normal and a geometric normal,
205    // flip the perturbed normal if the geometric normal is pointing away
206    // from the observer.
207    // n is the perturbed vector that we want to align
208    // i is the incident vector
209    // ng is the geometric normal of the surface
210    forall(| add(T) | multiply(T) | lessthan(T) | fromint(T) | subtract(T))
211    vec2(T) faceforward(vec2(T) n, vec2(T) i, vec2(T) ng) {
212        return dot(ng, i) < (T){0} ? n : -n;
213    }
214
215    }
216}
217
218forall(dtype ostype, otype T | writeable(T, ostype) | vec2_t(T)) {
219    ostype & ?|?( ostype & os, vec2(T) v) with (v) {
220        return os | '<' | x | ',' | y | '>';
221    }
222    void ?|?( ostype & os, vec2(T) v ) with (v) {
223        (ostype &)(os | v); ends(os);
224    }
225}
Note: See TracBrowser for help on using the repository browser.