1595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/*
2595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Copyright 2013 The Android Open Source Project
3595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
4595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
5595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * you may not use this file except in compliance with the License.
6595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * You may obtain a copy of the License at
7595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
8595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
9595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
10595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Unless required by applicable law or agreed to in writing, software
11595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
12595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * See the License for the specific language governing permissions and
14595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * limitations under the License.
15595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */
16595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
17595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
181d77b719d51a01cbd6954a048fb64e79d50a950eMathias Agopian#pragma once
19595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <math.h>
21595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#include <stdint.h>
22595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#include <sys/types.h>
23595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <cmath>
255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <limits>
265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy#include <iostream>
275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
28595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#define PURE __attribute__((pure))
29595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
30caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#if __cplusplus >= 201402L
31caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#define CONSTEXPR constexpr
32caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#else
33caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#define CONSTEXPR
34caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#endif
35caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy
36595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopiannamespace android {
375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guynamespace details {
38595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian// -------------------------------------------------------------------------------------
39595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
40595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/*
41595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * No user serviceable parts here.
42595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
43595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * Don't use this file directly, instead include ui/vec{2|3|4}.h
44595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */
45595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
46595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/*
471d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments
48595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * operators on a vector of type BASE<T>.
49595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
50595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * BASE only needs to implement operator[] and size().
511d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian * By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically
52595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * get all the functionality here.
53595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */
54595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate <template<typename T> class VECTOR, typename T>
561d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianclass TVecAddOperators {
57595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianpublic:
58595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    /* compound assignment from a another vector of the same size but different
59595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * element type.
60595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
615d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename OTHER>
625d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator +=(const VECTOR<OTHER>& v) {
635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
645d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] += v[i];
66595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
68595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename OTHER>
705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator -=(const VECTOR<OTHER>& v) {
715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] -= v[i];
74595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
76595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
771d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian
781d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    /* compound assignment from a another vector of the same type.
791d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * These operators can be used for implicit conversion and  handle operations
801d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * like "vector *= scalar" by letting the compiler implicitly convert a scalar
811d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * to a vector (assuming the BASE<T> allows it).
821d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     */
835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator +=(const VECTOR<T>& v) {
845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] += v[i];
87595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
89595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator -=(const VECTOR<T>& v) {
915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] -= v[i];
94595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
96595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
97595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
981d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    /*
991d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * NOTE: the functions below ARE NOT member methods. They are friend functions
1001d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * with they definition inlined with their declaration. This makes these
1011d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * template functions available to the compiler when (and only when) this class
1021d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * is instantiated, at which point they're only templated on the 2nd parameter
1031d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * (the first one, BASE<T> being known).
104595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
1051d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian
1065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    /* The operators below handle operation between vectors of the same size
1071d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * but of a different element type.
1081d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     */
1091d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    template<typename RT>
1105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator +(VECTOR<T> lv, const VECTOR<RT>& rv) {
1115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
1125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv += rv;
1131d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    }
1141d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    template<typename RT>
1155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator -(VECTOR<T> lv, const VECTOR<RT>& rv) {
1165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
1175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv -= rv;
1181d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    }
1191d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian
1201d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    /* The operators below (which are not templates once this class is instanced,
1211d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * i.e.: BASE<T> is known) can be used for implicit conversion on both sides.
1225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * These handle operations like "vector + scalar" and "scalar + vector" by
1231d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * letting the compiler implicitly convert a scalar to a vector (assuming
1241d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * the BASE<T> allows it).
1251d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     */
1265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator +(VECTOR<T> lv, const VECTOR<T>& rv) {
1275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
1285d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv += rv;
1291d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    }
1305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator -(VECTOR<T> lv, const VECTOR<T>& rv) {
1315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
1325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv -= rv;
1331d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    }
1341d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian};
1351d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian
1365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename T> class VECTOR, typename T>
1371d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianclass TVecProductOperators {
1381d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopianpublic:
1391d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    /* compound assignment from a another vector of the same size but different
1401d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * element type.
1411d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     */
1425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename OTHER>
1435d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator *=(const VECTOR<OTHER>& v) {
1445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
1455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
1465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] *= v[i];
147595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
1485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
149595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
1505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename OTHER>
1515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator /=(const VECTOR<OTHER>& v) {
1525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
1535d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
1545d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] /= v[i];
155595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
1565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
157595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
1581d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian
1591d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian    /* compound assignment from a another vector of the same type.
1601d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * These operators can be used for implicit conversion and  handle operations
1611d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * like "vector *= scalar" by letting the compiler implicitly convert a scalar
1621d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     * to a vector (assuming the BASE<T> allows it).
1631d4d8f94e2989b7c8667602304df9059d2701653Mathias Agopian     */
1645d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator *=(const VECTOR<T>& v) {
1655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
1665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
1675d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] *= v[i];
168595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
1695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
170595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
1715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator /=(const VECTOR<T>& v) {
1725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this);
1735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lhs.size(); i++) {
1745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            lhs[i] /= v[i];
175595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
1765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lhs;
177595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
178595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
179595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    /*
180595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * NOTE: the functions below ARE NOT member methods. They are friend functions
181595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * with they definition inlined with their declaration. This makes these
182595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * template functions available to the compiler when (and only when) this class
183595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * is instantiated, at which point they're only templated on the 2nd parameter
184595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * (the first one, BASE<T> being known).
185595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
186595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
1875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    /* The operators below handle operation between vectors of the same size
188595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * but of a different element type.
189595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
190595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
1915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator *(VECTOR<T> lv, const VECTOR<RT>& rv) {
1925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
1935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv *= rv;
194595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
195595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
1965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator /(VECTOR<T> lv, const VECTOR<RT>& rv) {
1975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
1985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv /= rv;
199595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
200595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
201595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    /* The operators below (which are not templates once this class is instanced,
202595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * i.e.: BASE<T> is known) can be used for implicit conversion on both sides.
203595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * These handle operations like "vector * scalar" and "scalar * vector" by
204595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * letting the compiler implicitly convert a scalar to a vector (assuming
205595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * the BASE<T> allows it).
206595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
2075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator *(VECTOR<T> lv, const VECTOR<T>& rv) {
2085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
2095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv *= rv;
210595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
2115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE operator /(VECTOR<T> lv, const VECTOR<T>& rv) {
2125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        // don't pass lv by reference because we need a copy anyways
2135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv /= rv;
214595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
215595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian};
216595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
217595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/*
218595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * TVecUnaryOperators implements unary operators on a vector of type BASE<T>.
219595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
220595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * BASE only needs to implement operator[] and size().
221595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically
222595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * get all the functionality here.
223595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
224595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * These operators are implemented as friend functions of TVecUnaryOperators<BASE, T>
225595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */
2265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename T> class VECTOR, typename T>
227595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianclass TVecUnaryOperators {
228595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianpublic:
2295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator ++() {
2305d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& rhs = static_cast<VECTOR<T>&>(*this);
2315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < rhs.size(); i++) {
232595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian            ++rhs[i];
233595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
234595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return rhs;
235595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
236caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy
2375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    VECTOR<T>& operator --() {
2385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T>& rhs = static_cast<VECTOR<T>&>(*this);
2395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < rhs.size(); i++) {
240595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian            --rhs[i];
241595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
242595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return rhs;
243595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
244caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy
245caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    CONSTEXPR VECTOR<T> operator -() const {
2465d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T> r(VECTOR<T>::NO_INIT);
2475d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this));
2485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < r.size(); i++) {
249595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian            r[i] = -rv[i];
250595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        }
251595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return r;
252595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
253595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian};
254595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
255595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/*
256595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * TVecComparisonOperators implements relational/comparison operators
257595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * on a vector of type BASE<T>.
258595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
259595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * BASE only needs to implement operator[] and size().
260595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically
261595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * get all the functionality here.
262595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */
2635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename T> class VECTOR, typename T>
264595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianclass TVecComparisonOperators {
265595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianpublic:
266595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    /*
267595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * NOTE: the functions below ARE NOT member methods. They are friend functions
268595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * with they definition inlined with their declaration. This makes these
269595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * template functions available to the compiler when (and only when) this class
270595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * is instantiated, at which point they're only templated on the 2nd parameter
271595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * (the first one, BASE<T> being known).
272595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
273595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
274595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    friend inline
2755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    bool PURE operator ==(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
2765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lv.size(); i++)
277595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian            if (lv[i] != rv[i])
278595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian                return false;
279595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return true;
280595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
281595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
282595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
283595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    friend inline
2845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    bool PURE operator !=(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
285595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return !operator ==(lv, rv);
286595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
287595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
288595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
289595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    friend inline
2905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    bool PURE operator >(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
2915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lv.size(); i++) {
2925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            if (lv[i] == rv[i]) {
2935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                continue;
2945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            }
2955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            return lv[i] > rv[i];
2965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
2975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return false;
298595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
299595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
300595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
301595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    friend inline
3025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr bool PURE operator <=(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
303595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return !(lv > rv);
304595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
305595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
306595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
307595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    friend inline
3085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    bool PURE operator <(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
3095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lv.size(); i++) {
3105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            if (lv[i] == rv[i]) {
3115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy                continue;
3125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            }
3135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            return lv[i] < rv[i];
3145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
3155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return false;
316595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
317595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
318595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
319595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    friend inline
3205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    constexpr bool PURE operator >=(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
321595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return !(lv < rv);
322595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
32311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
32411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename RT>
32511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline
326eedb69abbde29ad3dd624f1f9dfc72e4f35d5234Romain Guy    CONSTEXPR VECTOR<bool> PURE equal(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
32711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<bool> r;
32811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < lv.size(); i++) {
32911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            r[i] = lv[i] == rv[i];
33011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
33111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return r;
33211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
33311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
33411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename RT>
33511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline
336eedb69abbde29ad3dd624f1f9dfc72e4f35d5234Romain Guy    CONSTEXPR VECTOR<bool> PURE notEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
33711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<bool> r;
33811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < lv.size(); i++) {
33911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            r[i] = lv[i] != rv[i];
34011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
34111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return r;
34211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
34311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
34411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename RT>
34511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline
346eedb69abbde29ad3dd624f1f9dfc72e4f35d5234Romain Guy    CONSTEXPR VECTOR<bool> PURE lessThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
34711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<bool> r;
34811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < lv.size(); i++) {
34911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            r[i] = lv[i] < rv[i];
35011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
35111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return r;
35211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
35311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
35411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename RT>
35511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline
356eedb69abbde29ad3dd624f1f9dfc72e4f35d5234Romain Guy    CONSTEXPR VECTOR<bool> PURE lessThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
35711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<bool> r;
35811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < lv.size(); i++) {
35911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            r[i] = lv[i] <= rv[i];
36011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
36111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return r;
36211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
36311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
36411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename RT>
36511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline
366eedb69abbde29ad3dd624f1f9dfc72e4f35d5234Romain Guy    CONSTEXPR VECTOR<bool> PURE greaterThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
36711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<bool> r;
36811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < lv.size(); i++) {
36911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            r[i] = lv[i] > rv[i];
37011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
37111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return r;
37211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
37311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
37411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename RT>
37511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline
376eedb69abbde29ad3dd624f1f9dfc72e4f35d5234Romain Guy    CONSTEXPR VECTOR<bool> PURE greaterThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
37711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<bool> r;
37811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < lv.size(); i++) {
37911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            r[i] = lv[i] >= rv[i];
38011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
38111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return r;
38211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
383595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian};
384595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
385595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian/*
386595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * TVecFunctions implements functions on a vector of type BASE<T>.
387595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian *
388595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * BASE only needs to implement operator[] and size().
389595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * By simply inheriting from TVecFunctions<BASE, T> BASE will automatically
390595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian * get all the functionality here.
391595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian */
3925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename T> class VECTOR, typename T>
393595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianclass TVecFunctions {
394595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopianpublic:
395595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    /*
396595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * NOTE: the functions below ARE NOT member methods. They are friend functions
397595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * with they definition inlined with their declaration. This makes these
398595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * template functions available to the compiler when (and only when) this class
399595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * is instantiated, at which point they're only templated on the 2nd parameter
400595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     * (the first one, BASE<T> being known).
401595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian     */
402595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
403caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR T PURE dot(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
404595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        T r(0);
4055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < lv.size(); i++) {
4065d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            //r = std::fma(lv[i], rv[i], r);
4075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            r += lv[i] * rv[i];
4085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
409595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return r;
410595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
411595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
4125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr T PURE norm(const VECTOR<T>& lv) {
4135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return std::sqrt(dot(lv, lv));
4145d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4155d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
4165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr T PURE length(const VECTOR<T>& lv) {
4175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return norm(lv);
4185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
4205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr T PURE norm2(const VECTOR<T>& lv) {
4215d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return dot(lv, lv);
4225d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
4245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr T PURE length2(const VECTOR<T>& lv) {
4255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return norm2(lv);
426595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
427595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
428595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    template<typename RT>
4295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr T PURE distance(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
430595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian        return length(rv - lv);
431595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
432595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
4335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    template<typename RT>
4345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr T PURE distance2(const VECTOR<T>& lv, const VECTOR<RT>& rv) {
4355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return length2(rv - lv);
4365d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
4385d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend inline constexpr VECTOR<T> PURE normalize(const VECTOR<T>& lv) {
4395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return lv * (T(1) / length(lv));
4405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
442caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline constexpr VECTOR<T> PURE rcp(VECTOR<T> v) {
4435d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return T(1) / v;
4445d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4455d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
446caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE abs(VECTOR<T> v) {
44711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4485d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::abs(v[i]);
4495d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4505d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4515d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4525d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
453caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE floor(VECTOR<T> v) {
45411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4555d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::floor(v[i]);
4565d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4575d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4585d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4595d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
460caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE ceil(VECTOR<T> v) {
46111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4625d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::ceil(v[i]);
4635d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4645d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4655d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4665d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
467caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE round(VECTOR<T> v) {
46811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4695d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::round(v[i]);
4705d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4715d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4725d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4735d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
474caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE inversesqrt(VECTOR<T> v) {
47511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = T(1) / std::sqrt(v[i]);
4775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
481caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE sqrt(VECTOR<T> v) {
48211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::sqrt(v[i]);
4845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
488caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE pow(VECTOR<T> v, T p) {
48911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
4905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::pow(v[i], p);
4915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
4925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
4935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
495caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE saturate(const VECTOR<T>& lv) {
4965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return clamp(lv, T(0), T(1));
4975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
4985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
499caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE clamp(VECTOR<T> v, T min, T max) {
50011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i< v.size(); i++) {
5015d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::min(max, std::max(min, v[i]));
5025d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5035d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
5045d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
5055d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
506caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE fma(const VECTOR<T>& lv, const VECTOR<T>& rv, VECTOR<T> a) {
50711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i<lv.size(); i++) {
5085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            //a[i] = std::fma(lv[i], rv[i], a[i]);
5095d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            a[i] += (lv[i] * rv[i]);
5105d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5115d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return a;
5125d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
5135d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
514caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE min(const VECTOR<T>& u, VECTOR<T> v) {
51511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
5165d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::min(u[i], v[i]);
5175d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5185d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
5195d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
5205d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
521caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE max(const VECTOR<T>& u, VECTOR<T> v) {
52211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
5235d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            v[i] = std::max(u[i], v[i]);
5245d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5255d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return v;
5265d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
5275d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
528caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR T PURE max(const VECTOR<T>& v) {
5295d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        T r(std::numeric_limits<T>::lowest());
53011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
5315d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            r = std::max(r, v[i]);
5325d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5335d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return r;
5345d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
5355d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
536caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR T PURE min(const VECTOR<T>& v) {
5375d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        T r(std::numeric_limits<T>::max());
53811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
5395d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            r = std::min(r, v[i]);
5405d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5415d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return r;
5425d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    }
543caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy
544caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    friend inline CONSTEXPR VECTOR<T> PURE apply(VECTOR<T> v, const std::function<T(T)>& f) {
54511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
546caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy            v[i] = f(v[i]);
547caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy        }
548caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy        return v;
549caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy    }
55011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
55111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline CONSTEXPR bool PURE any(const VECTOR<T>& v) {
55211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
55311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            if (v[i] != T(0)) return true;
55411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
55511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return false;
55611ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
55711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
55811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline CONSTEXPR bool PURE all(const VECTOR<T>& v) {
55911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        bool result = true;
56011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
56111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            result &= (v[i] != T(0));
56211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
56311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return result;
56411ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
56511ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy
56611ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    template<typename R>
56711ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    friend inline CONSTEXPR VECTOR<R> PURE map(VECTOR<T> v, const std::function<R(T)>& f) {
56811ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        VECTOR<R> result;
56911ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        for (size_t i = 0; i < v.size(); i++) {
57011ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy            result[i] = f(v[i]);
57111ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        }
57211ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy        return result;
57311ecb63414d2fea2f4217db8bb06a998bcf8b425Romain Guy    }
5745d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy};
5755d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy
5765d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy/*
5775d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * TVecDebug implements functions on a vector of type BASE<T>.
5785d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy *
5795d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * BASE only needs to implement operator[] and size().
5805d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * By simply inheriting from TVecDebug<BASE, T> BASE will automatically
5815d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy * get all the functionality here.
5825d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy */
5835d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guytemplate<template<typename T> class VECTOR, typename T>
5845d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guyclass TVecDebug {
5855d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guypublic:
5865d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    /*
5875d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * NOTE: the functions below ARE NOT member methods. They are friend functions
5885d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * with they definition inlined with their declaration. This makes these
5895d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * template functions available to the compiler when (and only when) this class
5905d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * is instantiated, at which point they're only templated on the 2nd parameter
5915d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     * (the first one, BASE<T> being known).
5925d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy     */
5935d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy    friend std::ostream& operator<<(std::ostream& stream, const VECTOR<T>& v) {
5945d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        stream << "< ";
5955d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        for (size_t i = 0; i < v.size() - 1; i++) {
5965d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy            stream << T(v[i]) << ", ";
5975d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        }
5985d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        stream << T(v[v.size() - 1]) << " >";
5995d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy        return stream;
600595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian    }
601595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian};
602595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
603caf2ca414f69d460c516e2370cf42bcf49178d95Romain Guy#undef CONSTEXPR
604595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian#undef PURE
605595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian
606595ea77f6bdb5e9d0ddd3305da7a44b56f326b2cMathias Agopian// -------------------------------------------------------------------------------------
6075d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}  // namespace details
6085d4bae7f170640e0e280b3ca8a22b18e80801a8aRomain Guy}  // namespace android
609