// Copyright (C) 2020-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

// expensive: * [1-9] * *
#include "bits/verify.h"
#include "bits/metahelpers.h"
#include "bits/conversions.h"

using std::experimental::simd_cast;

template <typename V, bool ConstProp, typename F>
  auto
  gen(const F& fun)
  {
    if constexpr (ConstProp)
      return V(fun);
    else
      return make_value_unknown(V(fun));
  }

template <typename V, bool ConstProp>
  void
  split_concat()
  {
    using T = typename V::value_type;
    if constexpr (V::size() * 3
		    <= std::experimental::simd_abi::max_fixed_size<T>)
      {
	V a(0), b(1), c(2);
	auto x = concat(a, b, c);
	COMPARE(x.size(), a.size() * 3);
	std::size_t i = 0;
	for (; i < a.size(); ++i)
	  {
	    COMPARE(x[i], T(0));
	  }
	for (; i < 2 * a.size(); ++i)
	  {
	    COMPARE(x[i], T(1));
	  }
	for (; i < 3 * a.size(); ++i)
	  {
	    COMPARE(x[i], T(2));
	  }
      }

    if constexpr (V::size() >= 4)
      {
	const V a = gen<V, ConstProp>([](auto i) -> T { return i; });
	constexpr auto N0 = V::size() / 4u;
	constexpr auto N1 = V::size() - 2 * N0;
	using V0 = std::experimental::simd<
		     T, std::experimental::simd_abi::deduce_t<T, N0>>;
	using V1 = std::experimental::simd<
		     T, std::experimental::simd_abi::deduce_t<T, N1>>;
	{
	  auto x = std::experimental::split<N0, N0, N1>(a);
	  COMPARE(std::tuple_size<decltype(x)>::value, 3u);
	  COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; }));
	  COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N0; }));
	  COMPARE(std::get<2>(x), V1([](auto i) -> T { return i + 2 * N0; }));
	  auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x));
	  // a and b may have different types if a was fixed_size<N> such that
	  // another ABI tag exists with equal N, then b will have the
	  // non-fixed-size ABI tag.
	  COMPARE(a.size(), b.size());
	  COMPARE(
	    b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); }));
	}
	{
	  auto x = std::experimental::split<N0, N1, N0>(a);
	  COMPARE(std::tuple_size<decltype(x)>::value, 3u);
	  COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; }));
	  COMPARE(std::get<1>(x), V1([](auto i) -> T { return i + N0; }));
	  COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; }));
	  auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x));
	  // a and b may have different types if a was fixed_size<N> such that
	  // another ABI tag exists with equal N, then b will have the
	  // non-fixed-size ABI tag.
	  COMPARE(a.size(), b.size());
	  COMPARE(
	    b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); }));
	}
	{
	  auto x = std::experimental::split<N1, N0, N0>(a);
	  COMPARE(std::tuple_size<decltype(x)>::value, 3u);
	  COMPARE(std::get<0>(x), V1([](auto i) -> T { return i; }));
	  COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N1; }));
	  COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; }));
	  auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x));
	  // a and b may have different types if a was fixed_size<N> such that
	  // another ABI tag exists with equal N, then b will have the
	  // non-fixed-size ABI tag.
	  COMPARE(a.size(), b.size());
	  COMPARE(
	    b, decltype(b)([](auto i) -> T { return (N1 + i) % V::size(); }));
	}
      }

    if constexpr (V::size() % 3 == 0)
      {
	const V a = gen<V, ConstProp>([](auto i) -> T { return i; });
	constexpr auto N0 = V::size() / 3;
	using V0 = std::experimental::simd<
		     T, std::experimental::simd_abi::deduce_t<T, N0>>;
	using V1 = std::experimental::simd<
	  T, std::experimental::simd_abi::deduce_t<T, 2 * N0>>;
	{
	  auto [x, y, z] = std::experimental::split<N0, N0, N0>(a);
	  COMPARE(x, V0([](auto i) -> T { return i; }));
	  COMPARE(y, V0([](auto i) -> T { return i + N0; }));
	  COMPARE(z, V0([](auto i) -> T { return i + N0 * 2; }));
	  auto b = concat(x, y, z);
	  COMPARE(a.size(), b.size());
	  COMPARE(b, simd_cast<decltype(b)>(a));
	  COMPARE(simd_cast<V>(b), a);
	}
	{
	  auto [x, y] = std::experimental::split<N0, 2 * N0>(a);
	  COMPARE(x, V0([](auto i) -> T { return i; }));
	  COMPARE(y, V1([](auto i) -> T { return i + N0; }));
	  auto b = concat(x, y);
	  COMPARE(a.size(), b.size());
	  COMPARE(b, simd_cast<decltype(b)>(a));
	  COMPARE(simd_cast<V>(b), a);
	}
	{
	  auto [x, y] = std::experimental::split<2 * N0, N0>(a);
	  COMPARE(x, V1([](auto i) -> T { return i; }));
	  COMPARE(y, V0([](auto i) -> T { return i + 2 * N0; }));
	  auto b = concat(x, y);
	  COMPARE(a.size(), b.size());
	  COMPARE(b, simd_cast<decltype(b)>(a));
	  COMPARE(simd_cast<V>(b), a);
	}
      }

    if constexpr ((V::size() & 1) == 0)
      {
	using std::experimental::simd;
	using std::experimental::simd_abi::deduce_t;
	using V0 = simd<T, deduce_t<T, V::size()>>;
	using V2 = simd<T, deduce_t<T, 2>>;
	using V3 = simd<T, deduce_t<T, V::size() / 2>>;

	const V a = gen<V, ConstProp>([](auto i) -> T { return i; });

	std::array<V2, V::size() / 2> v2s = std::experimental::split<V2>(a);
	int offset = 0;
	for (V2 test : v2s)
	  {
	    COMPARE(test, V2([&](auto i) -> T { return i + offset; }));
	    offset += 2;
	  }
	COMPARE(concat(v2s), simd_cast<V0>(a));

	std::array<V3, 2> v3s = std::experimental::split<V3>(a);
	COMPARE(v3s[0], V3([](auto i) -> T { return i; }));
	COMPARE(v3s[1], V3([](auto i) -> T { return i + V3::size(); }));
	COMPARE(concat(v3s), simd_cast<V0>(a));
      }
  }

template <typename V>
  void
  test()
  {
    split_concat<V, true>();
    split_concat<V, false>();
  }
