/*
 * This file is part of hipSYCL, a SYCL implementation based on CUDA/HIP
 *
 * Copyright (c) 2018 Aksel Alpay
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef HIPSYCL_VEC_HPP
#define HIPSYCL_VEC_HPP

#include <cstddef>
#include <type_traits>
#include "backend/backend.hpp"
#include "types.hpp"
#include "access.hpp"
#include "multi_ptr.hpp"
#include "detail/vec.hpp"
#include "detail/vec_common.hpp"
#include "detail/vec_swizzle.hpp"

namespace hipsycl {
namespace sycl {
namespace detail {


template<class T, int N, class Function>
HIPSYCL_UNIVERSAL_TARGET
inline void transform_vector(vec<T,N>& v, Function f);

template<class T, int N, class Function>
HIPSYCL_UNIVERSAL_TARGET
inline vec<T,N> binary_vector_operation(const vec<T,N>& a,
                                        const vec<T,N>& b,
                                        Function f);

template<class T, int N, class Function>
HIPSYCL_UNIVERSAL_TARGET
inline vec<T,N> trinary_vector_operation(const vec<T,N>& a,
                                         const vec<T,N>& b,
                                         const vec<T,N>& c,
                                         Function f);




} // detail



struct elem
{
  static constexpr int x = 0;
  static constexpr int y = 1;
  static constexpr int z = 2;
  static constexpr int w = 3;
  static constexpr int r = 0;
  static constexpr int g = 1;
  static constexpr int b = 2;
  static constexpr int a = 3;
  static constexpr int s0 = 0;
  static constexpr int s1 = 1;
  static constexpr int s2 = 2;
  static constexpr int s3 = 3;
  static constexpr int s4 = 4;
  static constexpr int s5 = 5;
  static constexpr int s6 = 6;
  static constexpr int s7 = 7;
  static constexpr int s8 = 8;
  static constexpr int s9 = 9;
  static constexpr int sA = 10;
  static constexpr int sB = 11;
  static constexpr int sC = 12;
  static constexpr int sD = 13;
  static constexpr int sE = 14;
  static constexpr int sF = 15;
};

template <typename dataT, int numElements>
class vec
{
  template<class T, int N, class Function>
  HIPSYCL_UNIVERSAL_TARGET
  friend void detail::transform_vector(vec<T,N>& v,
                                       Function f);

  template<class T, int N, class Function>
  HIPSYCL_UNIVERSAL_TARGET
  friend vec<T,N> detail::binary_vector_operation(const vec<T,N>& a,
                                                  const vec<T,N>& b,
                                                  Function f);

  template<class T, int N, class Function>
  HIPSYCL_UNIVERSAL_TARGET
  friend vec<T,N> detail::trinary_vector_operation(const vec<T,N>& a,
                                                   const vec<T,N>& b,
                                                   const vec<T,N>& c,
                                                   Function f);

  template<class T, int N>
  friend class vec;

  HIPSYCL_UNIVERSAL_TARGET
  explicit vec(const detail::vector_impl<dataT,numElements>& v)
    : _impl{v}
  {}

  /// Initialization from numElements scalars
  template<int... Indices, typename... Args>
  HIPSYCL_UNIVERSAL_TARGET
  void scalar_init(detail::vector_index_sequence<Indices...>, Args... args)
  {
    static_assert(sizeof...(args) == numElements,
                  "Invalid number of arguments for vector "
                  "initialization");

    auto dummy_initializer = { ((_impl.template set<Indices>(args)), 0)... };
  }

  /// Initialization from single scalar
  template<int... Indices>
  HIPSYCL_UNIVERSAL_TARGET
  void broadcast_scalar_init(detail::vector_index_sequence<Indices...>, dataT x)
  {
    auto dummy_initializer = { ((_impl.template set<Indices>(x)), 0)... };
  }

  template<int Start_index, int N, int... Indices>
  HIPSYCL_UNIVERSAL_TARGET
  constexpr void init_from_vec(detail::vector_index_sequence<Indices...>,
                     const vec<dataT,N>& other)
  {
    auto dummy_initializer =
    {
      ((_impl.template set<Start_index + Indices>(
                                   other._impl.template get<Indices>())), 0)...
    };
  }

  template<int Start_index, int N>
  HIPSYCL_UNIVERSAL_TARGET
  constexpr void init_from_vec(const vec<dataT,N>& other)
  {
    init_from_vec<Start_index>(typename detail::vector_impl<dataT,N>::indices(),
                               other);
  }

  template<int Position>
  HIPSYCL_UNIVERSAL_TARGET
  constexpr void init_from_argument()
  {
    static_assert (Position == numElements, "Invalid number of vector "
                                            "constructor arguments.");
  }

  template<int Position, typename... Args>
  HIPSYCL_UNIVERSAL_TARGET
  constexpr void init_from_argument(dataT scalar,
                                    const Args&... args)
  {
    _impl.template set<Position>(scalar);
    init_from_argument<Position+1>(args...);
  }

  template<int Position, int N, typename... Args>
  HIPSYCL_UNIVERSAL_TARGET
  constexpr void init_from_argument(const vec<dataT,N>& v,
                                    const Args&... args)
  {
    init_from_vec<Position>(v);
    init_from_argument<Position + N>(args...);
  }

  template<int... swizzleIndices>
  HIPSYCL_UNIVERSAL_TARGET
  auto swizzle_index_sequence(detail::vector_index_sequence<swizzleIndices...>) const
  {
    return swizzle<swizzleIndices...>();
  }
public:
  static_assert(numElements == 1 ||
                numElements == 2 ||
                numElements == 3 ||
                numElements == 4 ||
                numElements == 8 ||
                numElements == 16,
                "Invalid number of vector elements. Allowed values: "
                "1,2,3,4,8,16");

  using element_type = dataT;

#ifdef SYCL_DEVICE_ONLY
  using vector_t = vec<dataT, numElements>;
#endif
  HIPSYCL_UNIVERSAL_TARGET
  vec()
    : _impl {}
  {}

  template<int Original_vector_size,
           int... Swizzle_indices>
  HIPSYCL_UNIVERSAL_TARGET
  vec(const detail::vec_swizzle<dataT, Original_vector_size, Swizzle_indices...>&
      swizzled_vec)
    : _impl{swizzled_vec.swizzled_access().get()}
  {}

  HIPSYCL_UNIVERSAL_TARGET
  explicit vec(const dataT &arg)
  {
    broadcast_scalar_init(typename detail::vector_impl<dataT,numElements>::indices(),
                          arg);
  }

  template <typename... argTN>
  HIPSYCL_UNIVERSAL_TARGET
  vec(const argTN&... args)
  {
    init_from_argument<0>(args...);
  }


  vec(const vec<dataT, numElements> &rhs) = default;

  // OpenCL interop is unsupported
//#ifdef SYCL_DEVICE_ONLY
  //vec(vector_t openclVector);
  //operator vector_t() const;
//#endif

  // Available only when: numElements == 1
  template<int N = numElements,
           std::enable_if_t<N == 1>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  operator dataT() const
  { return _impl.template get<0>(); }

  HIPSYCL_UNIVERSAL_TARGET
  size_t get_count() const
  { return numElements; }

  HIPSYCL_UNIVERSAL_TARGET
  size_t get_size() const
  { return numElements * sizeof (dataT); }

  // ToDo
  template <typename convertT, rounding_mode roundingMode>
  vec<convertT, numElements> convert() const;

  // ToDo
  template <typename asT>
  asT as() const;

#define HIPSYCL_DEFINE_VECTOR_ACCESS_IF(condition, name, id) \
  template<int N = numElements, \
           std::enable_if_t<(id < N) && (condition)>* = nullptr> \
  HIPSYCL_UNIVERSAL_TARGET \
  dataT& name() \
  { return _impl.template get<id>(); } \
  \
  template<int N = numElements, \
           std::enable_if_t<(id < N) && (condition)>* = nullptr> \
  HIPSYCL_UNIVERSAL_TARGET \
  dataT name() const \
  { return _impl.template get<id>(); }

  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 4, x, 0)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 4, y, 1)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 4, z, 2)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 4, w, 3)

  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements == 4, r, 0)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements == 4, g, 1)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements == 4, b, 2)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements == 4, a, 3)

  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s0, 0)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s1, 1)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s2, 2)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s3, 3)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s4, 4)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s5, 5)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s6, 6)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s7, 7)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s8, 8)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, s9, 9)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, sA, 10)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, sB, 11)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, sC, 12)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, sD, 13)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, sE, 14)
  HIPSYCL_DEFINE_VECTOR_ACCESS_IF(numElements <= 16, sF, 15)


  template<int... swizzleIndexes>
  HIPSYCL_UNIVERSAL_TARGET
  auto swizzle() const
  {
    return detail::vec_swizzle<dataT, numElements, swizzleIndexes...>{
      const_cast<detail::vector_impl<dataT,numElements>&>(_impl)
    };
  }

  template<int N = numElements,
           std::enable_if_t<(N > 1)>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  auto lo() const
  {
    return swizzle_index_sequence(
          typename detail::vector_impl<dataT, numElements>::lo_indices());
  }

  template<int N = numElements,
           std::enable_if_t<(N > 1)>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  auto hi() const
  {
    return swizzle_index_sequence(
          typename detail::vector_impl<dataT, numElements>::hi_indices());
  }

  template<int N = numElements,
           std::enable_if_t<(N > 1)>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  auto even() const
  {
    return swizzle_index_sequence(
          typename detail::vector_impl<dataT, numElements>::even_indices());
  }

  template<int N = numElements,
           std::enable_if_t<(N > 1)>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  auto odd() const
  {
    return swizzle_index_sequence(
          typename detail::vector_impl<dataT, numElements>::odd_indices());
  }

#ifdef SYCL_SIMPLE_SWIZZLES
#define HIPSYCL_DEFINE_VECTOR_SWIZZLE2(name, N, i0, i1) \
  template<int n = numElements, \
           std::enable_if_t<(n >= N && n <= 4)>* = nullptr> \
  HIPSYCL_UNIVERSAL_TARGET \
  auto name() const \
  {return swizzle<i0,i1>(); }

#define HIPSYCL_DEFINE_VECTOR_SWIZZLE3(name, N, i0, i1, i2) \
  template<int n = numElements, \
           std::enable_if_t<(n >= N && n <= 4)>* = nullptr> \
  HIPSYCL_UNIVERSAL_TARGET \
  auto name() const \
  {return swizzle<i0,i1,i2>(); }

#define HIPSYCL_DEFINE_VECTOR_SWIZZLE4(name, i0, i1, i2, i3) \
  template<int n = numElements, \
           std::enable_if_t<(n == 4)>* = nullptr> \
  HIPSYCL_UNIVERSAL_TARGET \
  auto name() const \
  {return swizzle<i0,i1,i2,i3>(); }


  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(xx, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(yx, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(xy, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(yy, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(xz, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(yz, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(zy, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(zx, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(zz, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(xw, 4, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(yw, 4, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(zw, 4, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(ww, 4, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(wx, 4, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(wy, 4, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE2(wz, 4, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xxx, 3, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yxx, 3, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zxx, 3, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xyx, 3, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yyx, 3, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zyx, 3, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xzx, 3, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yzx, 3, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zzx, 3, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xxy, 3, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yxy, 3, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zxy, 3, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xyy, 3, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yyy, 3, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zyy, 3, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xzy, 3, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yzy, 3, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zzy, 3, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xxz, 3, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yxz, 3, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zxz, 3, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xyz, 3, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yyz, 3, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zyz, 3, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xzz, 3, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yzz, 3, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zzz, 3, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xxw, 4, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yxw, 4, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zxw, 4, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xyw, 4, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yyw, 4, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zyw, 4, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xzw, 4, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yzw, 4, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zzw, 4, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xwx, 4, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(ywx, 4, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zwx, 4, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xwy, 4, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(ywy, 4, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zwy, 4, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xwz, 4, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(ywz, 4, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zwz, 4, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wxx, 4, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wyx, 4, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wzx, 4, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wxy, 4, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wyy, 4, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wzy, 4, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wxz, 4, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wyz, 4, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wzz, 4, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(xww, 4, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(yww, 4, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(zww, 4, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wwx, 4, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wwy, 4, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(wwz, 4, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE3(www, 4, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxxx, 0, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrrr, 0, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxxx, 1, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grrr, 1, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxxx, 2, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brrr, 2, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxxx, 3, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arrr, 3, 0, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyxx, 0, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgrr, 0, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyxx, 1, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggrr, 1, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyxx, 2, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgrr, 2, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyxx, 3, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agrr, 3, 1, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzxx, 0, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbrr, 0, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzxx, 1, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbrr, 1, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzxx, 2, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbrr, 2, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzxx, 3, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abrr, 3, 2, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwxx, 0, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rarr, 0, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywxx, 1, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(garr, 1, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwxx, 2, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(barr, 2, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwxx, 3, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aarr, 3, 3, 0, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxyx, 0, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrgr, 0, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxyx, 1, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grgr, 1, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxyx, 2, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brgr, 2, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxyx, 3, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(argr, 3, 0, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyyx, 0, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rggr, 0, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyyx, 1, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gggr, 1, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyyx, 2, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bggr, 2, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyyx, 3, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aggr, 3, 1, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzyx, 0, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbgr, 0, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzyx, 1, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbgr, 1, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzyx, 2, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbgr, 2, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzyx, 3, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abgr, 3, 2, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwyx, 0, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ragr, 0, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywyx, 1, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gagr, 1, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwyx, 2, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bagr, 2, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwyx, 3, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aagr, 3, 3, 1, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxzx, 0, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrbr, 0, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxzx, 1, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grbr, 1, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxzx, 2, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brbr, 2, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxzx, 3, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arbr, 3, 0, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyzx, 0, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgbr, 0, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyzx, 1, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggbr, 1, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyzx, 2, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgbr, 2, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyzx, 3, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agbr, 3, 1, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzzx, 0, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbbr, 0, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzzx, 1, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbbr, 1, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzzx, 2, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbbr, 2, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzzx, 3, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abbr, 3, 2, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwzx, 0, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rabr, 0, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywzx, 1, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gabr, 1, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwzx, 2, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(babr, 2, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwzx, 3, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aabr, 3, 3, 2, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxwx, 0, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrar, 0, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxwx, 1, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grar, 1, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxwx, 2, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brar, 2, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxwx, 3, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arar, 3, 0, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xywx, 0, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgar, 0, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yywx, 1, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggar, 1, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zywx, 2, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgar, 2, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wywx, 3, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agar, 3, 1, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzwx, 0, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbar, 0, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzwx, 1, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbar, 1, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzwx, 2, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbar, 2, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzwx, 3, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abar, 3, 2, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwwx, 0, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(raar, 0, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywwx, 1, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gaar, 1, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwwx, 2, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(baar, 2, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwwx, 3, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aaar, 3, 3, 3, 0)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxxy, 0, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrrg, 0, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxxy, 1, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grrg, 1, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxxy, 2, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brrg, 2, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxxy, 3, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arrg, 3, 0, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyxy, 0, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgrg, 0, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyxy, 1, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggrg, 1, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyxy, 2, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgrg, 2, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyxy, 3, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agrg, 3, 1, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzxy, 0, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbrg, 0, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzxy, 1, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbrg, 1, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzxy, 2, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbrg, 2, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzxy, 3, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abrg, 3, 2, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwxy, 0, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rarg, 0, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywxy, 1, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(garg, 1, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwxy, 2, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(barg, 2, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwxy, 3, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aarg, 3, 3, 0, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxyy, 0, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrgg, 0, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxyy, 1, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grgg, 1, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxyy, 2, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brgg, 2, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxyy, 3, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(argg, 3, 0, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyyy, 0, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rggg, 0, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyyy, 1, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gggg, 1, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyyy, 2, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bggg, 2, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyyy, 3, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aggg, 3, 1, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzyy, 0, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbgg, 0, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzyy, 1, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbgg, 1, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzyy, 2, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbgg, 2, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzyy, 3, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abgg, 3, 2, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwyy, 0, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ragg, 0, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywyy, 1, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gagg, 1, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwyy, 2, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bagg, 2, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwyy, 3, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aagg, 3, 3, 1, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxzy, 0, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrbg, 0, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxzy, 1, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grbg, 1, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxzy, 2, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brbg, 2, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxzy, 3, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arbg, 3, 0, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyzy, 0, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgbg, 0, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyzy, 1, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggbg, 1, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyzy, 2, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgbg, 2, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyzy, 3, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agbg, 3, 1, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzzy, 0, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbbg, 0, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzzy, 1, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbbg, 1, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzzy, 2, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbbg, 2, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzzy, 3, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abbg, 3, 2, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwzy, 0, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rabg, 0, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywzy, 1, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gabg, 1, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwzy, 2, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(babg, 2, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwzy, 3, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aabg, 3, 3, 2, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxwy, 0, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrag, 0, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxwy, 1, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grag, 1, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxwy, 2, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brag, 2, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxwy, 3, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arag, 3, 0, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xywy, 0, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgag, 0, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yywy, 1, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggag, 1, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zywy, 2, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgag, 2, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wywy, 3, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agag, 3, 1, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzwy, 0, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbag, 0, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzwy, 1, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbag, 1, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzwy, 2, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbag, 2, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzwy, 3, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abag, 3, 2, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwwy, 0, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(raag, 0, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywwy, 1, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gaag, 1, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwwy, 2, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(baag, 2, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwwy, 3, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aaag, 3, 3, 3, 1)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxxz, 0, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrrb, 0, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxxz, 1, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grrb, 1, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxxz, 2, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brrb, 2, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxxz, 3, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arrb, 3, 0, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyxz, 0, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgrb, 0, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyxz, 1, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggrb, 1, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyxz, 2, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgrb, 2, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyxz, 3, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agrb, 3, 1, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzxz, 0, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbrb, 0, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzxz, 1, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbrb, 1, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzxz, 2, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbrb, 2, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzxz, 3, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abrb, 3, 2, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwxz, 0, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rarb, 0, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywxz, 1, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(garb, 1, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwxz, 2, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(barb, 2, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwxz, 3, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aarb, 3, 3, 0, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxyz, 0, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrgb, 0, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxyz, 1, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grgb, 1, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxyz, 2, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brgb, 2, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxyz, 3, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(argb, 3, 0, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyyz, 0, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rggb, 0, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyyz, 1, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gggb, 1, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyyz, 2, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bggb, 2, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyyz, 3, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aggb, 3, 1, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzyz, 0, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbgb, 0, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzyz, 1, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbgb, 1, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzyz, 2, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbgb, 2, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzyz, 3, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abgb, 3, 2, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwyz, 0, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ragb, 0, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywyz, 1, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gagb, 1, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwyz, 2, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bagb, 2, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwyz, 3, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aagb, 3, 3, 1, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxzz, 0, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrbb, 0, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxzz, 1, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grbb, 1, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxzz, 2, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brbb, 2, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxzz, 3, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arbb, 3, 0, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyzz, 0, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgbb, 0, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyzz, 1, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggbb, 1, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyzz, 2, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgbb, 2, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyzz, 3, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agbb, 3, 1, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzzz, 0, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbbb, 0, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzzz, 1, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbbb, 1, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzzz, 2, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbbb, 2, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzzz, 3, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abbb, 3, 2, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwzz, 0, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rabb, 0, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywzz, 1, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gabb, 1, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwzz, 2, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(babb, 2, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwzz, 3, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aabb, 3, 3, 2, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxwz, 0, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrab, 0, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxwz, 1, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grab, 1, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxwz, 2, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brab, 2, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxwz, 3, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arab, 3, 0, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xywz, 0, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgab, 0, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yywz, 1, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggab, 1, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zywz, 2, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgab, 2, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wywz, 3, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agab, 3, 1, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzwz, 0, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbab, 0, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzwz, 1, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbab, 1, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzwz, 2, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbab, 2, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzwz, 3, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abab, 3, 2, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwwz, 0, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(raab, 0, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywwz, 1, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gaab, 1, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwwz, 2, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(baab, 2, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwwz, 3, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aaab, 3, 3, 3, 2)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxxw, 0, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrra, 0, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxxw, 1, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grra, 1, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxxw, 2, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brra, 2, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxxw, 3, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arra, 3, 0, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyxw, 0, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgra, 0, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyxw, 1, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggra, 1, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyxw, 2, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgra, 2, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyxw, 3, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agra, 3, 1, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzxw, 0, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbra, 0, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzxw, 1, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbra, 1, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzxw, 2, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbra, 2, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzxw, 3, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abra, 3, 2, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwxw, 0, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rara, 0, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywxw, 1, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gara, 1, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwxw, 2, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bara, 2, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwxw, 3, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aara, 3, 3, 0, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxyw, 0, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrga, 0, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxyw, 1, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grga, 1, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxyw, 2, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brga, 2, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxyw, 3, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arga, 3, 0, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyyw, 0, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgga, 0, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyyw, 1, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggga, 1, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyyw, 2, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgga, 2, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyyw, 3, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agga, 3, 1, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzyw, 0, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbga, 0, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzyw, 1, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbga, 1, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzyw, 2, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbga, 2, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzyw, 3, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abga, 3, 2, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwyw, 0, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(raga, 0, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywyw, 1, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gaga, 1, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwyw, 2, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(baga, 2, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwyw, 3, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aaga, 3, 3, 1, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxzw, 0, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rrba, 0, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxzw, 1, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(grba, 1, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxzw, 2, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(brba, 2, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxzw, 3, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(arba, 3, 0, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyzw, 0, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgba, 0, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyzw, 1, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggba, 1, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyzw, 2, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgba, 2, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyzw, 3, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agba, 3, 1, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzzw, 0, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbba, 0, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzzw, 1, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbba, 1, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzzw, 2, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbba, 2, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzzw, 3, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abba, 3, 2, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwzw, 0, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(raba, 0, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywzw, 1, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gaba, 1, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwzw, 2, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(baba, 2, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwzw, 3, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aaba, 3, 3, 2, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xxww, 0, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rraa, 0, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yxww, 1, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(graa, 1, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zxww, 2, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(braa, 2, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wxww, 3, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(araa, 3, 0, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xyww, 0, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rgaa, 0, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yyww, 1, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ggaa, 1, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zyww, 2, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bgaa, 2, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wyww, 3, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(agaa, 3, 1, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xzww, 0, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(rbaa, 0, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(yzww, 1, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gbaa, 1, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zzww, 2, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(bbaa, 2, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wzww, 3, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(abaa, 3, 2, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(xwww, 0, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(raaa, 0, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(ywww, 1, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(gaaa, 1, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(zwww, 2, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(baaa, 2, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(wwww, 3, 3, 3, 3)
  HIPSYCL_DEFINE_VECTOR_SWIZZLE4(aaaa, 3, 3, 3, 3)
#endif


  // ToDo: load and store member functions
  template <access::address_space addressSpace>
  HIPSYCL_UNIVERSAL_TARGET
  void load(size_t offset, multi_ptr<dataT, addressSpace> ptr);
  template <access::address_space addressSpace>
  HIPSYCL_UNIVERSAL_TARGET
  void store(size_t offset, multi_ptr<dataT, addressSpace> ptr) const;

  // OP is: +, -, *, /, %
  /* When OP is % available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator+(const vec<dataT, numElements> &rhs) const
  { return vec<dataT,numElements>{_impl + rhs._impl}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator-(const vec<dataT, numElements> &rhs) const
  { return vec<dataT,numElements>{_impl - rhs._impl}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator*(const vec<dataT, numElements> &rhs) const
  { return vec<dataT,numElements>{_impl * rhs._impl}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator/(const vec<dataT, numElements> &rhs) const
  { return vec<dataT,numElements>{_impl / rhs._impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator%(const vec<dataT, numElements> &rhs) const
  { return vec<dataT,numElements>{_impl % rhs._impl}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator+(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl + rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator-(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl - rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator*(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl * rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator/(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl / rhs}; }


  // OP is: +=, -=, *=, /=, %=
  /* When OP is %= available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator+=(const vec<dataT, numElements> &rhs)
  { _impl += rhs._impl; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator-=(const vec<dataT, numElements> &rhs)
  { _impl -= rhs._impl; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator*=(const vec<dataT, numElements> &rhs)
  { _impl *= rhs._impl; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator/=(const vec<dataT, numElements> &rhs)
  { _impl /= rhs._impl; return *this; }


  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator%=(const vec<dataT, numElements> &rhs)
  { _impl %= rhs._impl; return *this; }


  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator+=(const dataT &rhs)
  { _impl += rhs; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator-=(const dataT &rhs)
  { _impl -= rhs; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator*=(const dataT &rhs)
  { _impl *= rhs; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator/=(const dataT &rhs)
  { _impl /= rhs; return *this; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator%=(const dataT &rhs)
  { _impl %= rhs; return *this; }

  // OP is: ++, --
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator++()
  { *this += 1; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator--()
  { *this -= 1; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator++(int)
  {
    vec<dataT, numElements> old = *this;
    ++(*this);
    return old;
  }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator--(int)
  {
    vec<dataT, numElements> old = *this;
    --(*this);
    return old;
  }

  // OP is: &, |, ˆ
  /* Available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator&(const vec<dataT,numElements> &rhs) const
  { return vec<dataT,numElements>{_impl & rhs._impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator|(const vec<dataT,numElements> &rhs) const
  { return vec<dataT,numElements>{_impl | rhs._impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator^(const vec<dataT,numElements> &rhs) const
  { return vec<dataT,numElements>{_impl ^ rhs._impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator&(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl & rhs}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator|(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl | rhs}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> operator^(const dataT &rhs) const
  { return vec<dataT,numElements>{_impl ^ rhs}; }

  // OP is: &=, |=, ˆ=
  /* Available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */
  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator&=(const vec<dataT,numElements>& rhs) const
  { _impl &= rhs._impl; return *this; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator|=(const vec<dataT,numElements>& rhs) const
  { _impl |= rhs._impl; return *this; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator^=(const vec<dataT,numElements>& rhs) const
  { _impl ^= rhs._impl; return *this; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator&=(const dataT& rhs) const
  { _impl &= rhs; return *this; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator|=(const dataT& rhs) const
  { _impl |= rhs; return *this; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator^=(const dataT& rhs) const
  { _impl ^= rhs; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator&& (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl && rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator|| (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl || rhs._impl
    };
  }

  // OP is: &&, ||
  HIPSYCL_UNIVERSAL_TARGET
  auto operator&& (const dataT &rhs) const
  { return (*this) && vec<dataT,numElements>{rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator|| (const dataT &rhs) const
  { return (*this) || vec<dataT,numElements>{rhs}; }

  // OP is: <<, >>
  /* Available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT,numElements> operator <<(const vec<dataT, numElements>& rhs) const
  { return vec<dataT,numElements>{_impl << rhs._impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT,numElements> operator >>(const vec<dataT, numElements>& rhs) const
  { return vec<dataT,numElements>{_impl >> rhs._impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT,numElements> operator <<(const dataT& rhs) const
  { return vec<dataT,numElements>{_impl << rhs}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT,numElements> operator >>(const dataT& rhs) const
  { return vec<dataT,numElements>{_impl >> rhs}; }

  // OP is: <<=, >>=
  /* Available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */
  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator<<=(const vec<dataT, numElements> &rhs)
  { _impl <<= rhs._impl; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator>>=(const vec<dataT, numElements> &rhs)
  { _impl >>= rhs._impl; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator<<=(const dataT &rhs)
  { _impl <<= rhs; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator>>=(const dataT &rhs)
  { _impl >>= rhs; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator== (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl == rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator!= (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl != rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator< (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl < rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator> (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl > rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator<= (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl <= rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator>= (const vec<dataT, numElements>& rhs) const
  {
    using result_type =
        typename detail::logical_vector_op_result<dataT>::type;

    return vec<result_type, numElements>{
      _impl >= rhs._impl
    };
  }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator== (const dataT &rhs) const
  { return (*this) == vec<dataT,numElements>{rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator!= (const dataT &rhs) const
  { return (*this) != vec<dataT,numElements>{rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator< (const dataT &rhs) const
  { return (*this) < vec<dataT,numElements>{rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator> (const dataT &rhs) const
  { return (*this) > vec<dataT,numElements>{rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator<= (const dataT &rhs) const
  { return (*this) <= vec<dataT,numElements>{rhs}; }

  HIPSYCL_UNIVERSAL_TARGET
  auto operator>= (const dataT &rhs) const
  { return (*this) >= vec<dataT,numElements>{rhs}; }

  /* Available only when: dataT != cl_float && dataT != cl_double
&& dataT != cl_half. */

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  auto operator~()
  { return vec<dataT, numElements>{~_impl}; }

  template<class t = dataT,
           std::enable_if_t<std::is_integral<t>::value>* = nullptr>
  HIPSYCL_UNIVERSAL_TARGET
  auto operator!()
  { return vec<dataT, numElements>{!_impl}; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator=(const vec<dataT, numElements> &rhs)
  { _impl = rhs._impl; return *this; }

  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements> &operator=(const dataT &rhs)
  {
    broadcast_scalar_init(typename detail::vector_impl<dataT,numElements>::indices(),
                          rhs);
    return *this;
  }

  template<int Original_vec_size,
           int... Access_indices>
  HIPSYCL_UNIVERSAL_TARGET
  vec<dataT, numElements>& operator=(
      const detail::vec_swizzle<dataT, Original_vec_size, Access_indices...>& swizzled_vec)
  {
    _impl = swizzled_vec.swizzled_access().get();
    return *this;
  }

private:
  detail::vector_impl<dataT, numElements> _impl;
};



// OP is: +, -, *, /, %
template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator+ (const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return rhs + lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator* (const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return rhs * lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator- (const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return vec<dataT,numElements>{lhs} - rhs; }


template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator/ (const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return vec<dataT,numElements>{lhs} / rhs; }

template <typename dataT, int numElements,
          std::enable_if_t<std::is_integral<dataT>::value>* = nullptr>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator% (const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return vec<dataT,numElements>{lhs} % rhs; }



// OP is: &, |, ˆ
// Available only when: dataT != cl_float && dataT != cl_double && dataT != cl_half.
template <typename dataT, int numElements,
          std::enable_if_t<std::is_integral<dataT>::value>* = nullptr>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator&(const dataT& lhs,
                                  const vec<dataT, numElements>& rhs)
{ return rhs & lhs; }

template <typename dataT, int numElements,
          std::enable_if_t<std::is_integral<dataT>::value>* = nullptr>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator|(const dataT& lhs,
                                  const vec<dataT, numElements>& rhs)
{ return rhs | lhs; }

template <typename dataT, int numElements,
          std::enable_if_t<std::is_integral<dataT>::value>* = nullptr>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator^(const dataT& lhs,
                                  const vec<dataT, numElements>& rhs)
{ return rhs ^ lhs; }


// OP is: &&, ||
template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator&&(const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs && lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator||(const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs || lhs; }


// OP is: <<, >>
// Available only when: dataT != cl_float && dataT != cl_double && dataT != cl_half.
template <typename dataT, int numElements,
          std::enable_if_t<std::is_integral<dataT>::value>* = nullptr>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator<<(const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return vec<dataT, numElements>{lhs} << rhs; }

template <typename dataT, int numElements,
          std::enable_if_t<std::is_integral<dataT>::value>* = nullptr>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator>>(const dataT &lhs,
                                   const vec<dataT, numElements> &rhs)
{ return vec<dataT, numElements>{lhs} >> rhs; }


// OP is: ==, !=, <, >, <=, >=
template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator==(const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs == lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator!=(const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs != lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator< (const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs >= lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator<=(const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs > lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator> (const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs <= lhs; }

template <typename dataT, int numElements>
HIPSYCL_UNIVERSAL_TARGET
inline
vec<dataT, numElements> operator>=(const dataT& lhs,
                                   const vec<dataT, numElements>& rhs)
{ return rhs < lhs; }


#define HIPSYCL_DEFINE_VECTOR_ALIAS(T, alias) \
  using alias ## 2  = vec<T, 2 >; \
  using alias ## 3  = vec<T, 3 >; \
  using alias ## 4  = vec<T, 4 >; \
  using alias ## 8  = vec<T, 8 >; \
  using alias ## 16 = vec<T, 16>

HIPSYCL_DEFINE_VECTOR_ALIAS(char, char);
HIPSYCL_DEFINE_VECTOR_ALIAS(short, short);
HIPSYCL_DEFINE_VECTOR_ALIAS(int, int);
HIPSYCL_DEFINE_VECTOR_ALIAS(long, long);
HIPSYCL_DEFINE_VECTOR_ALIAS(float, float);
HIPSYCL_DEFINE_VECTOR_ALIAS(double, double);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::hp_float, half);

HIPSYCL_DEFINE_VECTOR_ALIAS(detail::s_char, cl_char);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::u_char, cl_uchar);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::s_short, cl_short);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::u_short, cl_ushort);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::s_int, cl_int);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::u_int, cl_uint);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::s_long, cl_long);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::u_long, cl_ulong);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::sp_float, cl_float);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::dp_float, cl_double);
HIPSYCL_DEFINE_VECTOR_ALIAS(detail::hp_float, cl_half);


HIPSYCL_DEFINE_VECTOR_ALIAS(signed char, schar);
HIPSYCL_DEFINE_VECTOR_ALIAS(unsigned char, uchar);
HIPSYCL_DEFINE_VECTOR_ALIAS(unsigned short, ushort);
HIPSYCL_DEFINE_VECTOR_ALIAS(unsigned int, uint);
HIPSYCL_DEFINE_VECTOR_ALIAS(unsigned long, ulong);
HIPSYCL_DEFINE_VECTOR_ALIAS(long long, longlong);
HIPSYCL_DEFINE_VECTOR_ALIAS(unsigned long long, ulonglong);



namespace detail {

template<class T, int N, class Function>
HIPSYCL_UNIVERSAL_TARGET
void transform_vector(vec<T,N>& v, Function f)
{
  v._impl.transform(f);
}

template<class T, int N, class Function>
HIPSYCL_UNIVERSAL_TARGET
vec<T,N> binary_vector_operation(const vec<T,N>& a,
                                 const vec<T,N>& b,
                                 Function f)
{
  return vec<T,N>(a._impl.binary_operation(f, b._impl));
}

template<class T, int N, class Function>
HIPSYCL_UNIVERSAL_TARGET
vec<T,N> trinary_vector_operation(const vec<T,N>& a,
                                  const vec<T,N>& b,
                                  const vec<T,N>& c,
                                  Function f)
{
  return vec<T,N>{
        vector_impl<T,N>::trinary_operation(f, a._impl, b._impl, c._impl)
  };
}

template<class T,
         int Original_vec_size,
         int... Access_indices>
HIPSYCL_UNIVERSAL_TARGET
vec_swizzle<T,Original_vec_size,Access_indices...>&
vec_swizzle<T,Original_vec_size,Access_indices...>::operator=(
    const vec<T, vec_swizzle<T,Original_vec_size,Access_indices...>::N>& rhs)
{
  _swizzled_access.set(rhs._impl);
  return *this;
}

} // namespace detail
} // namespace sycl
} // namespace hipsycl


#endif
