// To test DynRankView - View interoperabitlity
// Deep copy of DynRankView to View
// Assignment operator
TEUCHOS_UNIT_TEST_TEMPLATE_3_DECL(
  Kokkos_DynRankView_FadFad, Interop, FadFadType, Layout, Device )
{
  typedef Kokkos::DynRankView<FadFadType,Layout,Device> DRViewType;
  typedef typename DRViewType::size_type size_type;
  typedef typename DRViewType::HostMirror host_view_type;

  typedef Kokkos::View<FadFadType**,Layout,Device> NoDynViewType;
  typedef typename NoDynViewType::HostMirror host_nondynrankview_type;

  const size_type num_rows = global_num_rows;
  const size_type num_cols = global_num_cols;
  const size_type outer_fad_size = global_outer_fad_size;
  const size_type inner_fad_size = global_inner_fad_size;

  // Create and fill view
  DRViewType v1("drview1", num_rows, num_cols, outer_fad_size+1);
  host_view_type h_v1 = Kokkos::create_mirror_view(v1);

  NoDynViewType ndv2("nodview2", num_rows, num_cols, outer_fad_size+1);
  host_nondynrankview_type h_ndv2 = Kokkos::create_mirror_view(ndv2);

  for (size_type i=0; i<num_rows; ++i)
    for (size_type j=0; j<num_cols; ++j)
      h_v1(i,j) = generate_nested_fad<FadFadType>(num_rows,
                                                  num_cols,
                                                  outer_fad_size,
                                                  inner_fad_size,
                                                  i, j);
  Kokkos::deep_copy(v1, h_v1); //v1 unused here

  // Deep copy DynRankView to View on device
  Kokkos::deep_copy(ndv2, h_v1);
  // Assign View to DynRankView
  DRViewType v2("drview2", num_rows, num_cols, outer_fad_size+1);
  v2 = ndv2 ;

  // Copy back
  host_view_type h_v2 = Kokkos::create_mirror_view(v2);
  Kokkos::deep_copy(h_v2, v2);

  // Check
  success = true;
  for (size_type i=0; i<num_rows; ++i) {
    for (size_type j=0; j<num_cols; ++j) {
      FadFadType f = generate_nested_fad<FadFadType>(num_rows,
                                                     num_cols,
                                                     outer_fad_size,
                                                     inner_fad_size,
                                                     i, j);
      success = success && checkNestedFads(f, h_v2(i,j), out);
    }
  }
}
TEUCHOS_UNIT_TEST_TEMPLATE_3_DECL(
  Kokkos_View_Fad, MultiplyConst, FadType, Layout, Device )
{
  typedef typename ApplyView<const FadType*,Layout,Device,Kokkos::MemoryUnmanaged>::type ConstViewType;
  typedef typename ApplyView<FadType*,Layout,Device>::type ViewType;
  typedef typename ViewType::size_type size_type;
  typedef typename ViewType::HostMirror host_view_type;

  const size_type num_rows = global_num_rows;
  const size_type fad_size = global_fad_size;

  // Create and fill views
  ViewType v1("view1", num_rows, fad_size+1);
  ViewType v2("view2", num_rows, fad_size+1);
  host_view_type h_v1 = Kokkos::create_mirror_view(v1);
  host_view_type h_v2 = Kokkos::create_mirror_view(v2);
  for (size_type i=0; i<num_rows; ++i) {
    h_v1(i) = generate_fad<FadType>(
      num_rows, size_type(2), fad_size, i, size_type(0));
    h_v2(i) = generate_fad<FadType>(
      num_rows, size_type(2), fad_size, i, size_type(1));
  }
  Kokkos::deep_copy(v1, h_v1);
  Kokkos::deep_copy(v2, h_v2);

  ConstViewType cv1 = v1;

  // Launch kernel
  ViewType v3("view3", num_rows, fad_size+1);
  MultiplyKernel<ConstViewType,ViewType,ViewType>::apply(cv1,v2,v3);

  // Copy back
  host_view_type h_v3 = Kokkos::create_mirror_view(v3);
  Kokkos::deep_copy(h_v3, v3);

  // Check
  success = true;
  for (size_type i=0; i<num_rows; ++i) {
    FadType f1 =
      generate_fad<FadType>(num_rows, size_type(2), fad_size, i, size_type(0));
    FadType f2 =
      generate_fad<FadType>(num_rows, size_type(2), fad_size, i, size_type(1));
    FadType f3 = f1*f2;
    success = success && checkFads(f3, h_v3(i), out);
  }
}
TEUCHOS_UNIT_TEST_TEMPLATE_3_DECL(
  Kokkos_DynRankView_FadFad, DeepCopy, FadFadType, Layout, Device )
{
  typedef Kokkos::DynRankView<FadFadType,Layout,Device> ViewType;
  typedef typename ViewType::size_type size_type;
  typedef typename ViewType::HostMirror host_view_type;

  const size_type num_rows = global_num_rows;
  const size_type num_cols = global_num_cols;
  const size_type outer_fad_size = global_outer_fad_size;
  const size_type inner_fad_size = global_inner_fad_size;

  // Create and fill view
  ViewType v1("view1", num_rows, num_cols, outer_fad_size+1);
  host_view_type h_v1 = Kokkos::create_mirror_view(v1);
  for (size_type i=0; i<num_rows; ++i)
    for (size_type j=0; j<num_cols; ++j)
      h_v1(i,j) = generate_nested_fad<FadFadType>(num_rows,
                                                  num_cols,
                                                  outer_fad_size,
                                                  inner_fad_size,
                                                  i, j);
  Kokkos::deep_copy(v1, h_v1);

  // Deep copy
  ViewType v2("view2", num_rows, num_cols, outer_fad_size+1);
  Kokkos::deep_copy(v2, v1);

  // Copy back
  host_view_type h_v2 = Kokkos::create_mirror_view(v2);
  Kokkos::deep_copy(h_v2, v2);

  // Check
  success = true;
  for (size_type i=0; i<num_rows; ++i) {
    for (size_type j=0; j<num_cols; ++j) {
      FadFadType f = generate_nested_fad<FadFadType>(num_rows,
                                                     num_cols,
                                                     outer_fad_size,
                                                     inner_fad_size,
                                                     i, j);
      success = success && checkNestedFads(f, h_v2(i,j), out);
    }
  }
}