skvx: allow more implicit conversions
Guarding the implict constructors and scalar/vector operations with std::is_convertible ought to make SkVx types feel more like normal C types, allowing implicit conversions exactly when the scalar equivalents would. This shouldn't change the behavior of any code, or make anything new possible... just nicer to read and write. Change-Id: Iff4b89012c5b8c7f7933e6841c925b81186bc614 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/201402 Commit-Queue: Mike Klein <mtklein@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com> Auto-Submit: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
a89cc05162
commit
f4438d56e9
@ -49,7 +49,10 @@ struct Vec {
|
||||
// Other operations on Vec should be defined outside the type.
|
||||
|
||||
Vec() = default;
|
||||
Vec(T x) : lo(x), hi(x) {}
|
||||
|
||||
template <typename U,
|
||||
typename=typename std::enable_if<std::is_convertible<U,T>::value>::type>
|
||||
Vec(U x) : lo(x), hi(x) {}
|
||||
|
||||
Vec(std::initializer_list<T> xs) {
|
||||
T vals[N] = {0};
|
||||
@ -77,7 +80,10 @@ struct Vec<1,T> {
|
||||
T val;
|
||||
|
||||
Vec() = default;
|
||||
Vec(T x) : val(x) {}
|
||||
|
||||
template <typename U,
|
||||
typename=typename std::enable_if<std::is_convertible<U,T>::value>::type>
|
||||
Vec(U x) : val(x) {}
|
||||
|
||||
Vec(std::initializer_list<T> xs) : val(xs.size() ? *xs.begin() : 0) {}
|
||||
|
||||
@ -101,9 +107,12 @@ struct Vec<1,T> {
|
||||
#endif
|
||||
|
||||
// Helps tamp down on the repetitive boilerplate.
|
||||
#define SINT template <int N, typename T> static inline
|
||||
#define SIT template < typename T> static inline
|
||||
#define SI static inline
|
||||
#define SI static inline
|
||||
#define SIT template < typename T> static inline
|
||||
#define SINT template <int N, typename T> static inline
|
||||
#define SINTU template <int N, typename T, typename U, \
|
||||
typename=typename std::enable_if<std::is_convertible<U,T>::value>::type> \
|
||||
static inline
|
||||
|
||||
template <typename D, typename S>
|
||||
SI D bit_pun(S s) {
|
||||
@ -296,46 +305,46 @@ SINT Vec<N,T> mad(Vec<N,T> f,
|
||||
|
||||
|
||||
// Scalar/vector operations just splat the scalar to a vector...
|
||||
SINT Vec<N,T> operator+ (T x, Vec<N,T> y) { return Vec<N,T>(x) + y; }
|
||||
SINT Vec<N,T> operator- (T x, Vec<N,T> y) { return Vec<N,T>(x) - y; }
|
||||
SINT Vec<N,T> operator* (T x, Vec<N,T> y) { return Vec<N,T>(x) * y; }
|
||||
SINT Vec<N,T> operator/ (T x, Vec<N,T> y) { return Vec<N,T>(x) / y; }
|
||||
SINT Vec<N,T> operator^ (T x, Vec<N,T> y) { return Vec<N,T>(x) ^ y; }
|
||||
SINT Vec<N,T> operator& (T x, Vec<N,T> y) { return Vec<N,T>(x) & y; }
|
||||
SINT Vec<N,T> operator| (T x, Vec<N,T> y) { return Vec<N,T>(x) | y; }
|
||||
SINT Vec<N,M<T>> operator==(T x, Vec<N,T> y) { return Vec<N,T>(x) == y; }
|
||||
SINT Vec<N,M<T>> operator!=(T x, Vec<N,T> y) { return Vec<N,T>(x) != y; }
|
||||
SINT Vec<N,M<T>> operator<=(T x, Vec<N,T> y) { return Vec<N,T>(x) <= y; }
|
||||
SINT Vec<N,M<T>> operator>=(T x, Vec<N,T> y) { return Vec<N,T>(x) >= y; }
|
||||
SINT Vec<N,M<T>> operator< (T x, Vec<N,T> y) { return Vec<N,T>(x) < y; }
|
||||
SINT Vec<N,M<T>> operator> (T x, Vec<N,T> y) { return Vec<N,T>(x) > y; }
|
||||
SINT Vec<N,T> min(T x, Vec<N,T> y) { return min(Vec<N,T>(x), y); }
|
||||
SINT Vec<N,T> max(T x, Vec<N,T> y) { return max(Vec<N,T>(x), y); }
|
||||
SINTU Vec<N,T> operator+ (U x, Vec<N,T> y) { return Vec<N,T>(x) + y; }
|
||||
SINTU Vec<N,T> operator- (U x, Vec<N,T> y) { return Vec<N,T>(x) - y; }
|
||||
SINTU Vec<N,T> operator* (U x, Vec<N,T> y) { return Vec<N,T>(x) * y; }
|
||||
SINTU Vec<N,T> operator/ (U x, Vec<N,T> y) { return Vec<N,T>(x) / y; }
|
||||
SINTU Vec<N,T> operator^ (U x, Vec<N,T> y) { return Vec<N,T>(x) ^ y; }
|
||||
SINTU Vec<N,T> operator& (U x, Vec<N,T> y) { return Vec<N,T>(x) & y; }
|
||||
SINTU Vec<N,T> operator| (U x, Vec<N,T> y) { return Vec<N,T>(x) | y; }
|
||||
SINTU Vec<N,M<T>> operator==(U x, Vec<N,T> y) { return Vec<N,T>(x) == y; }
|
||||
SINTU Vec<N,M<T>> operator!=(U x, Vec<N,T> y) { return Vec<N,T>(x) != y; }
|
||||
SINTU Vec<N,M<T>> operator<=(U x, Vec<N,T> y) { return Vec<N,T>(x) <= y; }
|
||||
SINTU Vec<N,M<T>> operator>=(U x, Vec<N,T> y) { return Vec<N,T>(x) >= y; }
|
||||
SINTU Vec<N,M<T>> operator< (U x, Vec<N,T> y) { return Vec<N,T>(x) < y; }
|
||||
SINTU Vec<N,M<T>> operator> (U x, Vec<N,T> y) { return Vec<N,T>(x) > y; }
|
||||
SINTU Vec<N,T> min(U x, Vec<N,T> y) { return min(Vec<N,T>(x), y); }
|
||||
SINTU Vec<N,T> max(U x, Vec<N,T> y) { return max(Vec<N,T>(x), y); }
|
||||
|
||||
// ... and same deal for vector/scalar operations.
|
||||
SINT Vec<N,T> operator+ (Vec<N,T> x, T y) { return x + Vec<N,T>(y); }
|
||||
SINT Vec<N,T> operator- (Vec<N,T> x, T y) { return x - Vec<N,T>(y); }
|
||||
SINT Vec<N,T> operator* (Vec<N,T> x, T y) { return x * Vec<N,T>(y); }
|
||||
SINT Vec<N,T> operator/ (Vec<N,T> x, T y) { return x / Vec<N,T>(y); }
|
||||
SINT Vec<N,T> operator^ (Vec<N,T> x, T y) { return x ^ Vec<N,T>(y); }
|
||||
SINT Vec<N,T> operator& (Vec<N,T> x, T y) { return x & Vec<N,T>(y); }
|
||||
SINT Vec<N,T> operator| (Vec<N,T> x, T y) { return x | Vec<N,T>(y); }
|
||||
SINT Vec<N,M<T>> operator==(Vec<N,T> x, T y) { return x == Vec<N,T>(y); }
|
||||
SINT Vec<N,M<T>> operator!=(Vec<N,T> x, T y) { return x != Vec<N,T>(y); }
|
||||
SINT Vec<N,M<T>> operator<=(Vec<N,T> x, T y) { return x <= Vec<N,T>(y); }
|
||||
SINT Vec<N,M<T>> operator>=(Vec<N,T> x, T y) { return x >= Vec<N,T>(y); }
|
||||
SINT Vec<N,M<T>> operator< (Vec<N,T> x, T y) { return x < Vec<N,T>(y); }
|
||||
SINT Vec<N,M<T>> operator> (Vec<N,T> x, T y) { return x > Vec<N,T>(y); }
|
||||
SINT Vec<N,T> min(Vec<N,T> x, T y) { return min(x, Vec<N,T>(y)); }
|
||||
SINT Vec<N,T> max(Vec<N,T> x, T y) { return max(x, Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T> operator+ (Vec<N,T> x, U y) { return x + Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> operator- (Vec<N,T> x, U y) { return x - Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> operator* (Vec<N,T> x, U y) { return x * Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> operator/ (Vec<N,T> x, U y) { return x / Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> operator^ (Vec<N,T> x, U y) { return x ^ Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> operator& (Vec<N,T> x, U y) { return x & Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> operator| (Vec<N,T> x, U y) { return x | Vec<N,T>(y); }
|
||||
SINTU Vec<N,M<T>> operator==(Vec<N,T> x, U y) { return x == Vec<N,T>(y); }
|
||||
SINTU Vec<N,M<T>> operator!=(Vec<N,T> x, U y) { return x != Vec<N,T>(y); }
|
||||
SINTU Vec<N,M<T>> operator<=(Vec<N,T> x, U y) { return x <= Vec<N,T>(y); }
|
||||
SINTU Vec<N,M<T>> operator>=(Vec<N,T> x, U y) { return x >= Vec<N,T>(y); }
|
||||
SINTU Vec<N,M<T>> operator< (Vec<N,T> x, U y) { return x < Vec<N,T>(y); }
|
||||
SINTU Vec<N,M<T>> operator> (Vec<N,T> x, U y) { return x > Vec<N,T>(y); }
|
||||
SINTU Vec<N,T> min(Vec<N,T> x, U y) { return min(x, Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T> max(Vec<N,T> x, U y) { return max(x, Vec<N,T>(y)); }
|
||||
|
||||
// All vector/scalar combinations for mad() with at least one vector.
|
||||
SINT Vec<N,T> mad(T f, Vec<N,T> m, Vec<N,T> a) { return Vec<N,T>(f)*m + a; }
|
||||
SINT Vec<N,T> mad(Vec<N,T> f, T m, Vec<N,T> a) { return f*Vec<N,T>(m) + a; }
|
||||
SINT Vec<N,T> mad(Vec<N,T> f, Vec<N,T> m, T a) { return f*m + Vec<N,T>(a); }
|
||||
SINT Vec<N,T> mad(Vec<N,T> f, T m, T a) { return f*Vec<N,T>(m) + Vec<N,T>(a); }
|
||||
SINT Vec<N,T> mad(T f, Vec<N,T> m, T a) { return Vec<N,T>(f)*m + Vec<N,T>(a); }
|
||||
SINT Vec<N,T> mad(T f, T m, Vec<N,T> a) { return Vec<N,T>(f)*Vec<N,T>(m) + a; }
|
||||
SINTU Vec<N,T> mad(U f, Vec<N,T> m, Vec<N,T> a) { return Vec<N,T>(f)*m + a; }
|
||||
SINTU Vec<N,T> mad(Vec<N,T> f, U m, Vec<N,T> a) { return f*Vec<N,T>(m) + a; }
|
||||
SINTU Vec<N,T> mad(Vec<N,T> f, Vec<N,T> m, U a) { return f*m + Vec<N,T>(a); }
|
||||
SINTU Vec<N,T> mad(Vec<N,T> f, U m, U a) { return f*Vec<N,T>(m) + Vec<N,T>(a); }
|
||||
SINTU Vec<N,T> mad(U f, Vec<N,T> m, U a) { return Vec<N,T>(f)*m + Vec<N,T>(a); }
|
||||
SINTU Vec<N,T> mad(U f, U m, Vec<N,T> a) { return Vec<N,T>(f)*Vec<N,T>(m) + a; }
|
||||
|
||||
// The various op= operators, for vectors...
|
||||
SINT Vec<N,T>& operator+=(Vec<N,T>& x, Vec<N,T> y) { return (x = x + y); }
|
||||
@ -347,13 +356,13 @@ SINT Vec<N,T>& operator&=(Vec<N,T>& x, Vec<N,T> y) { return (x = x & y); }
|
||||
SINT Vec<N,T>& operator|=(Vec<N,T>& x, Vec<N,T> y) { return (x = x | y); }
|
||||
|
||||
// ... for scalars...
|
||||
SINT Vec<N,T>& operator+=(Vec<N,T>& x, T y) { return (x = x + Vec<N,T>(y)); }
|
||||
SINT Vec<N,T>& operator-=(Vec<N,T>& x, T y) { return (x = x - Vec<N,T>(y)); }
|
||||
SINT Vec<N,T>& operator*=(Vec<N,T>& x, T y) { return (x = x * Vec<N,T>(y)); }
|
||||
SINT Vec<N,T>& operator/=(Vec<N,T>& x, T y) { return (x = x / Vec<N,T>(y)); }
|
||||
SINT Vec<N,T>& operator^=(Vec<N,T>& x, T y) { return (x = x ^ Vec<N,T>(y)); }
|
||||
SINT Vec<N,T>& operator&=(Vec<N,T>& x, T y) { return (x = x & Vec<N,T>(y)); }
|
||||
SINT Vec<N,T>& operator|=(Vec<N,T>& x, T y) { return (x = x | Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator+=(Vec<N,T>& x, U y) { return (x = x + Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator-=(Vec<N,T>& x, U y) { return (x = x - Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator*=(Vec<N,T>& x, U y) { return (x = x * Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator/=(Vec<N,T>& x, U y) { return (x = x / Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator^=(Vec<N,T>& x, U y) { return (x = x ^ Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator&=(Vec<N,T>& x, U y) { return (x = x & Vec<N,T>(y)); }
|
||||
SINTU Vec<N,T>& operator|=(Vec<N,T>& x, U y) { return (x = x | Vec<N,T>(y)); }
|
||||
|
||||
// ... and for shifts.
|
||||
SINT Vec<N,T>& operator<<=(Vec<N,T>& x, int bits) { return (x = x << bits); }
|
||||
@ -434,6 +443,7 @@ namespace skvx {
|
||||
} // namespace skvx
|
||||
#endif // !defined(SKNX_NO_SIMD)
|
||||
|
||||
#undef SINTU
|
||||
#undef SINT
|
||||
#undef SIT
|
||||
#undef SI
|
||||
|
@ -132,4 +132,14 @@ DEF_TEST(SkVx, r) {
|
||||
REPORTER_ASSERT(r, all(shuffle<2,1> (float4{1,2,3,4}) == float2{3,2}));
|
||||
REPORTER_ASSERT(r, all(shuffle<2,1,2,1,2,1,2,1>(float4{1,2,3,4}) == float8{3,2,3,2,3,2,3,2}));
|
||||
REPORTER_ASSERT(r, all(shuffle<3,3,3,3> (float4{1,2,3,4}) == float4{4,4,4,4}));
|
||||
|
||||
// Test that mixed types can be used where they make sense. Mostly about ergonomics.
|
||||
REPORTER_ASSERT(r, all(float4{1,2,3,4} < 5));
|
||||
REPORTER_ASSERT(r, all( byte4{1,2,3,4} < 5));
|
||||
REPORTER_ASSERT(r, all( int4{1,2,3,4} < 5.0f));
|
||||
float4 five = 5;
|
||||
REPORTER_ASSERT(r, all(five == 5.0f));
|
||||
REPORTER_ASSERT(r, all(five == 5));
|
||||
|
||||
REPORTER_ASSERT(r, all(max(2, min(float4{1,2,3,4}, 3)) == float4{2,2,3,3}));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user