RavEngine
Loading...
Searching...
No Matches
vec_float.h
1//----------------------------------------------------------------------------//
2// //
3// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
4// and distributed under the MIT License (MIT). //
5// //
6// Copyright (c) Guillaume Blanc //
7// //
8// Permission is hereby granted, free of charge, to any person obtaining a //
9// copy of this software and associated documentation files (the "Software"), //
10// to deal in the Software without restriction, including without limitation //
11// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
12// and/or sell copies of the Software, and to permit persons to whom the //
13// Software is furnished to do so, subject to the following conditions: //
14// //
15// The above copyright notice and this permission notice shall be included in //
16// all copies or substantial portions of the Software. //
17// //
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
21// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
24// DEALINGS IN THE SOFTWARE. //
25// //
26//----------------------------------------------------------------------------//
27
28#ifndef OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
29#define OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
30
31#include <cassert>
32#include <cmath>
33
34#include "ozz/base/maths/math_constant.h"
35#include "ozz/base/platform.h"
36
37namespace ozz {
38namespace math {
39
40// Declares a 2d float vector.
41struct OZZ_BASE_DLL Float2 {
42 float x, y;
43
44 // Constructs an uninitialized vector.
45 OZZ_INLINE Float2() {}
46
47 // Constructs a vector initialized with _f value.
48 explicit OZZ_INLINE Float2(float _f) : x(_f), y(_f) {}
49
50 // Constructs a vector initialized with _x and _y values.
51 OZZ_INLINE Float2(float _x, float _y) : x(_x), y(_y) {}
52
53 // Returns a vector with all components set to 0.
54 static OZZ_INLINE Float2 zero() { return Float2(0.f); }
55
56 // Returns a vector with all components set to 1.
57 static OZZ_INLINE Float2 one() { return Float2(1.f); }
58
59 // Returns a unitary vector x.
60 static OZZ_INLINE Float2 x_axis() { return Float2(1.f, 0.f); }
61
62 // Returns a unitary vector y.
63 static OZZ_INLINE Float2 y_axis() { return Float2(0.f, 1.f); }
64};
65
66// Declares a 3d float vector.
67struct OZZ_BASE_DLL Float3 {
68 float x, y, z;
69
70 // Constructs an uninitialized vector.
71 OZZ_INLINE Float3() {}
72
73 // Constructs a vector initialized with _f value.
74 explicit OZZ_INLINE Float3(float _f) : x(_f), y(_f), z(_f) {}
75
76 // Constructs a vector initialized with _x, _y and _z values.
77 OZZ_INLINE Float3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
78
79 // Returns a vector initialized with _v.x, _v.y and _z values.
80 OZZ_INLINE Float3(Float2 _v, float _z) : x(_v.x), y(_v.y), z(_z) {}
81
82 // Returns a vector with all components set to 0.
83 static OZZ_INLINE Float3 zero() { return Float3(0.f); }
84
85 // Returns a vector with all components set to 1.
86 static OZZ_INLINE Float3 one() { return Float3(1.f); }
87
88 // Returns a unitary vector x.
89 static OZZ_INLINE Float3 x_axis() { return Float3(1.f, 0.f, 0.f); }
90
91 // Returns a unitary vector y.
92 static OZZ_INLINE Float3 y_axis() { return Float3(0.f, 1.f, 0.f); }
93
94 // Returns a unitary vector z.
95 static OZZ_INLINE Float3 z_axis() { return Float3(0.f, 0.f, 1.f); }
96};
97
98// Declares a 4d float vector.
99struct OZZ_BASE_DLL Float4 {
100 float x, y, z, w;
101
102 // Constructs an uninitialized vector.
103 OZZ_INLINE Float4() {}
104
105 // Constructs a vector initialized with _f value.
106 explicit OZZ_INLINE Float4(float _f) : x(_f), y(_f), z(_f), w(_f) {}
107
108 // Constructs a vector initialized with _x, _y, _z and _w values.
109 OZZ_INLINE Float4(float _x, float _y, float _z, float _w)
110 : x(_x), y(_y), z(_z), w(_w) {}
111
112 // Constructs a vector initialized with _v.x, _v.y, _v.z and _w values.
113 OZZ_INLINE Float4(Float3 _v, float _w) : x(_v.x), y(_v.y), z(_v.z), w(_w) {}
114
115 // Constructs a vector initialized with _v.x, _v.y, _z and _w values.
116 OZZ_INLINE Float4(Float2 _v, float _z, float _w)
117 : x(_v.x), y(_v.y), z(_z), w(_w) {}
118
119 // Returns a vector with all components set to 0.
120 static OZZ_INLINE Float4 zero() { return Float4(0.f); }
121
122 // Returns a vector with all components set to 1.
123 static OZZ_INLINE Float4 one() { return Float4(1.f); }
124
125 // Returns a unitary vector x.
126 static OZZ_INLINE Float4 x_axis() { return Float4(1.f, 0.f, 0.f, 0.f); }
127
128 // Returns a unitary vector y.
129 static OZZ_INLINE Float4 y_axis() { return Float4(0.f, 1.f, 0.f, 0.f); }
130
131 // Returns a unitary vector z.
132 static OZZ_INLINE Float4 z_axis() { return Float4(0.f, 0.f, 1.f, 0.f); }
133
134 // Returns a unitary vector w.
135 static OZZ_INLINE Float4 w_axis() { return Float4(0.f, 0.f, 0.f, 1.f); }
136};
137
138// Returns per element addition of _a and _b using operator +.
139OZZ_INLINE Float4 operator+(const Float4& _a, const Float4& _b) {
140 return Float4(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z, _a.w + _b.w);
141}
142OZZ_INLINE Float3 operator+(const Float3& _a, const Float3& _b) {
143 return Float3(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z);
144}
145OZZ_INLINE Float2 operator+(const Float2& _a, const Float2& _b) {
146 return Float2(_a.x + _b.x, _a.y + _b.y);
147}
148
149// Returns per element subtraction of _a and _b using operator -.
150OZZ_INLINE Float4 operator-(const Float4& _a, const Float4& _b) {
151 return Float4(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z, _a.w - _b.w);
152}
153OZZ_INLINE Float3 operator-(const Float3& _a, const Float3& _b) {
154 return Float3(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z);
155}
156OZZ_INLINE Float2 operator-(const Float2& _a, const Float2& _b) {
157 return Float2(_a.x - _b.x, _a.y - _b.y);
158}
159
160// Returns per element negative value of _v.
161OZZ_INLINE Float4 operator-(const Float4& _v) {
162 return Float4(-_v.x, -_v.y, -_v.z, -_v.w);
163}
164OZZ_INLINE Float3 operator-(const Float3& _v) {
165 return Float3(-_v.x, -_v.y, -_v.z);
166}
167OZZ_INLINE Float2 operator-(const Float2& _v) { return Float2(-_v.x, -_v.y); }
168
169// Returns per element multiplication of _a and _b using operator *.
170OZZ_INLINE Float4 operator*(const Float4& _a, const Float4& _b) {
171 return Float4(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z, _a.w * _b.w);
172}
173OZZ_INLINE Float3 operator*(const Float3& _a, const Float3& _b) {
174 return Float3(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z);
175}
176OZZ_INLINE Float2 operator*(const Float2& _a, const Float2& _b) {
177 return Float2(_a.x * _b.x, _a.y * _b.y);
178}
179
180// Returns per element multiplication of _a and scalar value _f using
181// operator *.
182OZZ_INLINE Float4 operator*(const Float4& _a, float _f) {
183 return Float4(_a.x * _f, _a.y * _f, _a.z * _f, _a.w * _f);
184}
185OZZ_INLINE Float3 operator*(const Float3& _a, float _f) {
186 return Float3(_a.x * _f, _a.y * _f, _a.z * _f);
187}
188OZZ_INLINE Float2 operator*(const Float2& _a, float _f) {
189 return Float2(_a.x * _f, _a.y * _f);
190}
191
192// Returns per element division of _a and _b using operator /.
193OZZ_INLINE Float4 operator/(const Float4& _a, const Float4& _b) {
194 return Float4(_a.x / _b.x, _a.y / _b.y, _a.z / _b.z, _a.w / _b.w);
195}
196OZZ_INLINE Float3 operator/(const Float3& _a, const Float3& _b) {
197 return Float3(_a.x / _b.x, _a.y / _b.y, _a.z / _b.z);
198}
199OZZ_INLINE Float2 operator/(const Float2& _a, const Float2& _b) {
200 return Float2(_a.x / _b.x, _a.y / _b.y);
201}
202
203// Returns per element division of _a and scalar value _f using operator/.
204OZZ_INLINE Float4 operator/(const Float4& _a, float _f) {
205 return Float4(_a.x / _f, _a.y / _f, _a.z / _f, _a.w / _f);
206}
207OZZ_INLINE Float3 operator/(const Float3& _a, float _f) {
208 return Float3(_a.x / _f, _a.y / _f, _a.z / _f);
209}
210OZZ_INLINE Float2 operator/(const Float2& _a, float _f) {
211 return Float2(_a.x / _f, _a.y / _f);
212}
213
214// Returns the (horizontal) addition of each element of _v.
215OZZ_INLINE float HAdd(const Float4& _v) { return _v.x + _v.y + _v.z + _v.w; }
216OZZ_INLINE float HAdd(const Float3& _v) { return _v.x + _v.y + _v.z; }
217OZZ_INLINE float HAdd(const Float2& _v) { return _v.x + _v.y; }
218
219// Returns the dot product of _a and _b.
220OZZ_INLINE float Dot(const Float4& _a, const Float4& _b) {
221 return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
222}
223OZZ_INLINE float Dot(const Float3& _a, const Float3& _b) {
224 return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
225}
226OZZ_INLINE float Dot(const Float2& _a, const Float2& _b) {
227 return _a.x * _b.x + _a.y * _b.y;
228}
229
230// Returns the cross product of _a and _b.
231OZZ_INLINE Float3 Cross(const Float3& _a, const Float3& _b) {
232 return Float3(_a.y * _b.z - _b.y * _a.z, _a.z * _b.x - _b.z * _a.x,
233 _a.x * _b.y - _b.x * _a.y);
234}
235
236// Returns the length |_v| of _v.
237OZZ_INLINE float Length(const Float4& _v) {
238 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
239 return std::sqrt(len2);
240}
241OZZ_INLINE float Length(const Float3& _v) {
242 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
243 return std::sqrt(len2);
244}
245OZZ_INLINE float Length(const Float2& _v) {
246 const float len2 = _v.x * _v.x + _v.y * _v.y;
247 return std::sqrt(len2);
248}
249
250// Returns the square length |_v|^2 of _v.
251OZZ_INLINE float LengthSqr(const Float4& _v) {
252 return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
253}
254OZZ_INLINE float LengthSqr(const Float3& _v) {
255 return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
256}
257OZZ_INLINE float LengthSqr(const Float2& _v) {
258 return _v.x * _v.x + _v.y * _v.y;
259}
260
261// Returns the normalized vector _v.
262OZZ_INLINE Float4 Normalize(const Float4& _v) {
263 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
264 assert(len2 != 0.f && "_v is not normalizable");
265 const float len = std::sqrt(len2);
266 return Float4(_v.x / len, _v.y / len, _v.z / len, _v.w / len);
267}
268OZZ_INLINE Float3 Normalize(const Float3& _v) {
269 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
270 assert(len2 != 0.f && "_v is not normalizable");
271 const float len = std::sqrt(len2);
272 return Float3(_v.x / len, _v.y / len, _v.z / len);
273}
274OZZ_INLINE Float2 Normalize(const Float2& _v) {
275 const float len2 = _v.x * _v.x + _v.y * _v.y;
276 assert(len2 != 0.f && "_v is not normalizable");
277 const float len = std::sqrt(len2);
278 return Float2(_v.x / len, _v.y / len);
279}
280
281// Returns true if _v is normalized.
282OZZ_INLINE bool IsNormalized(const Float4& _v) {
283 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
284 return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
285}
286OZZ_INLINE bool IsNormalized(const Float3& _v) {
287 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
288 return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
289}
290OZZ_INLINE bool IsNormalized(const Float2& _v) {
291 const float len2 = _v.x * _v.x + _v.y * _v.y;
292 return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
293}
294
295// Returns the normalized vector _v if the norm of _v is not 0.
296// Otherwise returns _safer.
297OZZ_INLINE Float4 NormalizeSafe(const Float4& _v, const Float4& _safer) {
298 assert(IsNormalized(_safer) && "_safer is not normalized");
299 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
300 if (len2 <= 0.f) {
301 return _safer;
302 }
303 const float len = std::sqrt(len2);
304 return Float4(_v.x / len, _v.y / len, _v.z / len, _v.w / len);
305}
306OZZ_INLINE Float3 NormalizeSafe(const Float3& _v, const Float3& _safer) {
307 assert(IsNormalized(_safer) && "_safer is not normalized");
308 const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
309 if (len2 <= 0.f) {
310 return _safer;
311 }
312 const float len = std::sqrt(len2);
313 return Float3(_v.x / len, _v.y / len, _v.z / len);
314}
315OZZ_INLINE Float2 NormalizeSafe(const Float2& _v, const Float2& _safer) {
316 assert(IsNormalized(_safer) && "_safer is not normalized");
317 const float len2 = _v.x * _v.x + _v.y * _v.y;
318 if (len2 <= 0.f) {
319 return _safer;
320 }
321 const float len = std::sqrt(len2);
322 return Float2(_v.x / len, _v.y / len);
323}
324
325// Returns the linear interpolation of _a and _b with coefficient _f.
326// _f is not limited to range [0,1].
327OZZ_INLINE Float4 Lerp(const Float4& _a, const Float4& _b, float _f) {
328 return Float4((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
329 (_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
330}
331OZZ_INLINE Float3 Lerp(const Float3& _a, const Float3& _b, float _f) {
332 return Float3((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
333 (_b.z - _a.z) * _f + _a.z);
334}
335OZZ_INLINE Float2 Lerp(const Float2& _a, const Float2& _b, float _f) {
336 return Float2((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y);
337}
338
339// Returns true if the distance between _a and _b is less than _tolerance.
340OZZ_INLINE bool Compare(const Float4& _a, const Float4& _b, float _tolerance) {
341 const math::Float4 diff = _a - _b;
342 return Dot(diff, diff) <= _tolerance * _tolerance;
343}
344OZZ_INLINE bool Compare(const Float3& _a, const Float3& _b, float _tolerance) {
345 const math::Float3 diff = _a - _b;
346 return Dot(diff, diff) <= _tolerance * _tolerance;
347}
348OZZ_INLINE bool Compare(const Float2& _a, const Float2& _b, float _tolerance) {
349 const math::Float2 diff = _a - _b;
350 return Dot(diff, diff) <= _tolerance * _tolerance;
351}
352
353// Returns true if each element of a is less than each element of _b.
354OZZ_INLINE bool operator<(const Float4& _a, const Float4& _b) {
355 return _a.x < _b.x && _a.y < _b.y && _a.z < _b.z && _a.w < _b.w;
356}
357OZZ_INLINE bool operator<(const Float3& _a, const Float3& _b) {
358 return _a.x < _b.x && _a.y < _b.y && _a.z < _b.z;
359}
360OZZ_INLINE bool operator<(const Float2& _a, const Float2& _b) {
361 return _a.x < _b.x && _a.y < _b.y;
362}
363
364// Returns true if each element of a is less or equal to each element of _b.
365OZZ_INLINE bool operator<=(const Float4& _a, const Float4& _b) {
366 return _a.x <= _b.x && _a.y <= _b.y && _a.z <= _b.z && _a.w <= _b.w;
367}
368OZZ_INLINE bool operator<=(const Float3& _a, const Float3& _b) {
369 return _a.x <= _b.x && _a.y <= _b.y && _a.z <= _b.z;
370}
371OZZ_INLINE bool operator<=(const Float2& _a, const Float2& _b) {
372 return _a.x <= _b.x && _a.y <= _b.y;
373}
374
375// Returns true if each element of a is greater than each element of _b.
376OZZ_INLINE bool operator>(const Float4& _a, const Float4& _b) {
377 return _a.x > _b.x && _a.y > _b.y && _a.z > _b.z && _a.w > _b.w;
378}
379OZZ_INLINE bool operator>(const Float3& _a, const Float3& _b) {
380 return _a.x > _b.x && _a.y > _b.y && _a.z > _b.z;
381}
382OZZ_INLINE bool operator>(const Float2& _a, const Float2& _b) {
383 return _a.x > _b.x && _a.y > _b.y;
384}
385
386// Returns true if each element of a is greater or equal to each element of _b.
387OZZ_INLINE bool operator>=(const Float4& _a, const Float4& _b) {
388 return _a.x >= _b.x && _a.y >= _b.y && _a.z >= _b.z && _a.w >= _b.w;
389}
390OZZ_INLINE bool operator>=(const Float3& _a, const Float3& _b) {
391 return _a.x >= _b.x && _a.y >= _b.y && _a.z >= _b.z;
392}
393OZZ_INLINE bool operator>=(const Float2& _a, const Float2& _b) {
394 return _a.x >= _b.x && _a.y >= _b.y;
395}
396
397// Returns true if each element of a is equal to each element of _b.
398// Uses a bitwise comparison of _a and _b, no tolerance is applied.
399OZZ_INLINE bool operator==(const Float4& _a, const Float4& _b) {
400 return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z && _a.w == _b.w;
401}
402OZZ_INLINE bool operator==(const Float3& _a, const Float3& _b) {
403 return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z;
404}
405OZZ_INLINE bool operator==(const Float2& _a, const Float2& _b) {
406 return _a.x == _b.x && _a.y == _b.y;
407}
408
409// Returns true if each element of a is different from each element of _b.
410// Uses a bitwise comparison of _a and _b, no tolerance is applied.
411OZZ_INLINE bool operator!=(const Float4& _a, const Float4& _b) {
412 return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z || _a.w != _b.w;
413}
414OZZ_INLINE bool operator!=(const Float3& _a, const Float3& _b) {
415 return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z;
416}
417OZZ_INLINE bool operator!=(const Float2& _a, const Float2& _b) {
418 return _a.x != _b.x || _a.y != _b.y;
419}
420
421// Returns the minimum of each element of _a and _b.
422OZZ_INLINE Float4 Min(const Float4& _a, const Float4& _b) {
423 return Float4(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y,
424 _a.z < _b.z ? _a.z : _b.z, _a.w < _b.w ? _a.w : _b.w);
425}
426OZZ_INLINE Float3 Min(const Float3& _a, const Float3& _b) {
427 return Float3(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y,
428 _a.z < _b.z ? _a.z : _b.z);
429}
430OZZ_INLINE Float2 Min(const Float2& _a, const Float2& _b) {
431 return Float2(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y);
432}
433
434// Returns the maximum of each element of _a and _b.
435OZZ_INLINE Float4 Max(const Float4& _a, const Float4& _b) {
436 return Float4(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y,
437 _a.z > _b.z ? _a.z : _b.z, _a.w > _b.w ? _a.w : _b.w);
438}
439OZZ_INLINE Float3 Max(const Float3& _a, const Float3& _b) {
440 return Float3(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y,
441 _a.z > _b.z ? _a.z : _b.z);
442}
443OZZ_INLINE Float2 Max(const Float2& _a, const Float2& _b) {
444 return Float2(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y);
445}
446
447// Clamps each element of _x between _a and _b.
448// _a must be less or equal to b;
449OZZ_INLINE Float4 Clamp(const Float4& _a, const Float4& _v, const Float4& _b) {
450 const Float4 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y,
451 _v.z < _b.z ? _v.z : _b.z, _v.w < _b.w ? _v.w : _b.w);
452 return Float4(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y,
453 _a.z > min.z ? _a.z : min.z, _a.w > min.w ? _a.w : min.w);
454}
455OZZ_INLINE Float3 Clamp(const Float3& _a, const Float3& _v, const Float3& _b) {
456 const Float3 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y,
457 _v.z < _b.z ? _v.z : _b.z);
458 return Float3(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y,
459 _a.z > min.z ? _a.z : min.z);
460}
461OZZ_INLINE Float2 Clamp(const Float2& _a, const Float2& _v, const Float2& _b) {
462 const Float2 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y);
463 return Float2(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y);
464}
465} // namespace math
466} // namespace ozz
467#endif // OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
Definition vec_float.h:41
Definition vec_float.h:67
Definition vec_float.h:99